diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/AddUserToAzureADRole.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/AddUserToAzureADRole.ps1 new file mode 100644 index 0000000..852a03e --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/AddUserToAzureADRole.ps1 @@ -0,0 +1,44 @@ +# Script to add user to an AzureAD role + +<# +You can find a list of available roles in the following Microsoft article +https://docs.microsoft.com/en-us/azure/active-directory/active-directory-assign-admin-roles-azure-portal +Double check using Get-AzureADDirectoryRole as they don't always have the same name in PowerShell as the GUI + +Built from the code example on the following Mircosoft page +https://docs.microsoft.com/en-us/powershell/module/azuread/add-azureaddirectoryrolemember?view=azureadps-2.0 +#> + + +# User UPN to assign role to +$roleUser = '' + +# Role Name to Assign +$roleName = '' + + +# Import AzureAD module and Connect +Import-Module AzureAD +Connect-AzureAD + +# Fetch user to assign to role +$roleMember = Get-AzureADUser -ObjectId $roleUser + +# Fetch role instance +$role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq $roleName} + +# If role instance does not exist, instantiate it based on the role template +if (!($role)) { + # Instantiate an instance of the role template + $roleTemplate = Get-AzureADDirectoryRoleTemplate | Where-Object {$_.displayName -eq $roleName} + Enable-AzureADDirectoryRole -RoleTemplateId $roleTemplate.ObjectId + + # Fetch role instance again + $role = Get-AzureADDirectoryRole | Where-Object {$_.displayName -eq $roleName} +} + +# Add user to role +Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $roleMember.ObjectId + +# Fetch role membership for role to confirm +Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | Get-AzureADUser diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddLicenceConditional.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddLicenceConditional.ps1 new file mode 100644 index 0000000..0d3ad19 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddLicenceConditional.ps1 @@ -0,0 +1,45 @@ +# Bulk add a new licence to users on the basis of what licence they currently have. +# +# An updated version of my previous MSOL script, now using AzureAD. +# This is useful for something like adding Office 365 ATP to everyone who currently has E3, for example. +# +# List of available SKUs can be obtained with (Get-AzureADSubscribedSku).SkuPartNumber +# + +# What licence do the users currently have? +$existingLicence = 'ENTERPRISEPACK' + +# What licence are we adding? +$licenceToAdd = 'ATP_ENTERPRISE' + +# Import AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Get all available licence skus +$allSkus = Get-AzureADSubscribedSku + +# Get sku ID for existing licence +$existingSkuID = ($allSkus | Where-Object {$_.SkuPartNumber -eq $existingLicence}).SkuId + +# Get sku ID for new licence +$newSkuID = ($allSkus | Where-Object {$_.SkuPartNumber -eq $licenceToAdd}).SkuId + +# Find everyone who has the existing licence but not the licence we're adding +$users = Get-AzureADUser -All $true | Where-Object {$_.AssignedLicenses.SkuId -match $existingSkuID -and !($_.AssignedLicenses.SkuId -match $newSkuID)} + +# Create a new licence object for the licence we're adding +$newLicense = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicense +$newLicense.SkuId = $newSkuID + +# Create a new assigned licenses object and add the licence we're adding to add licenses +$newLicenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses +$newLicenses.AddLicenses = $newLicense + +# Add the new licence to each user in the list +foreach ($user in $users) { + Set-AzureADUserLicense -ObjectId $user.UserPrincipalName -AssignedLicenses $newLicenses +} + +# Disconnect from AzureAD +Disconnect-AzureAD diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddLicences.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddLicences.ps1 new file mode 100644 index 0000000..2c0ecb2 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddLicences.ps1 @@ -0,0 +1,53 @@ +# Bulk add additional licences to a list of users. +# +# An updated version of my previous MSOL script, now using AzureAD. +# +# List of available SKUs can be obtained with (Get-AzureADSubscribedSku).SkuPartNumber +# + +# Where is the list of user UPN's? +$userListPath = 'C:\Temp\UserList.txt' + +# What licences are we adding? +$licencesToAdd = @('ENTERPRISEPACK','ATP_ENTERPRISE','EMSPREMIUM') + +# Import AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Import list of users from file +$userList = Get-Content -Path $userListPath | Sort-Object + +# Get all available licence skus +$newSkuIDs = (Get-AzureADSubscribedSku | Where-Object {$_.SkuPartNumber -in $licencesToAdd}).SkuId + +# Create a licenses object +$licenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses + +# Add the licences to add to the licences object +foreach ($newSkuID in $newSkuIDs) { + $newLicense = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicense + $newLicense.SkuId = $newSkuID + $licenses.AddLicenses += $newLicense +} + +# Add the licenses +foreach ($username in $userList) { + try { + $user = Get-AzureADUser -ObjectId $username -ErrorAction Stop + if ($user.AccountEnabled -eq $true) { + Set-AzureADUserLicense -ObjectId $user.UserPrincipalName -AssignedLicenses $licenses -ErrorAction Stop + Write-Output -InputObject ('Licence(s) added for user account ' + $user.UserPrincipalName + '.') + } + else { + Write-Output -InputObject ('User account ' + $user.UserPrincipalName + ' is disabled.') + } + } + catch { + Write-Output -InputObject ('There was a problem updating licences for user account ' + $user.UserPrincipalName + '.') + Write-Output -InputObject $Error[0] + } +} + +# Disconnect from AzureAD +Disconnect-AzureAD diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddUserToAzureADRoles.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddUserToAzureADRoles.ps1 new file mode 100644 index 0000000..21d6ef1 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkAddUserToAzureADRoles.ps1 @@ -0,0 +1,58 @@ +# Script to add multiple users to multiple AzureAD roles + +<# +You can find a list of available roles in the following Microsoft article +https://docs.microsoft.com/en-us/azure/active-directory/active-directory-assign-admin-roles-azure-portal +Double check using Get-AzureADDirectoryRole as they don't always have the same name in PowerShell as the GUI + +Built from the code example on the following Mircosoft page +https://docs.microsoft.com/en-us/powershell/module/azuread/add-azureaddirectoryrolemember?view=azureadps-2.0 +#> + + +# User UPNs to assign roles to +$roleUsers = @('') + +# Role Names to Assign +$roleNames = @('') + + +# Import AzureAD module and Connect +Import-Module AzureAD +Connect-AzureAD + +# Run through the list of users +foreach ($roleUser in $roleUsers) { + # Fetch user to assign to role + $roleMember = Get-AzureADUser -ObjectId $roleUser + + # Run through the list of roles + foreach ($roleName in $roleNames) { + # Fetch User Account Administrator role instance + $role = Get-AzureADDirectoryRole | Where-Object { $_.displayName -eq $roleName } + + # If role instance does not exist, instantiate it based on the role template + if (!($role)) { + # Instantiate an instance of the role template + $roleTemplate = Get-AzureADDirectoryRoleTemplate | Where-Object { $_.displayName -eq $roleName } + Enable-AzureADDirectoryRole -RoleTemplateId $roleTemplate.ObjectId + + # Fetch User Account Administrator role instance again + $role = Get-AzureADDirectoryRole | Where-Object { $_.displayName -eq $roleName } + } + + # Get existing users with the role assigned + $existingRoleUsers = (Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId).UserPrincipalName + + # Assign role to new user if not already in the list + if ($roleMember.UserPrincipalName -notin $existingRoleUsers) { + Add-AzureADDirectoryRoleMember -ObjectId $role.ObjectId -RefObjectId $roleMember.ObjectId -ErrorAction Stop + } + } +} + +# Uncomment to fetch role membership for each role to confirm +#foreach ($roleName in $roleNames) { +# Write-Output -InputObject ('Members for role: ' + $roleName) +# Get-AzureADDirectoryRoleMember -ObjectId $role.ObjectId | Get-AzureADUser | Where-Object {$_.UserPrincipalName -in $roleUsers} | Format-List -Property DisplayName,UserPrincipalName +#} diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkDisableGuestAccounts.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkDisableGuestAccounts.ps1 new file mode 100644 index 0000000..a4022ee --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkDisableGuestAccounts.ps1 @@ -0,0 +1,29 @@ +# Script to bulk disable guest accounts in Azure AD, either all or for a specific domain +# + +# Are we disabling for a specific guest domain? Leave blank for all guests. +$guestDomain = '' + +# Install the AzureAD module, uncomment if required +#Install-Module -Name AzureAD + +# Import the AzureAD module and connect to Azure AD +Import-Module -Name AzureAD +Connect-AzureAD + +# Get a list of all guests from Azure AD either matching the domain or all guests +if ($guestDomain -ne '') { + $guestAccounts = Get-AzureADUser -All $true | Where-Object { $_.AccountEnabled -eq $true -and $_.UserType -eq 'Guest' -and $_.Mail -like ('*' + $guestDomain) } +} +else { + $guestAccounts = Get-AzureADUser -All $true | Where-Object { $_.AccountEnabled -eq $true -and $_.UserType -eq 'Guest' } +} + +# Disable the guest accounts +try { + $guestAccounts | Set-AzureADUser -AccountEnabled $false -ErrorAction Stop + Write-Output -InputObject ('The specified guest accounts have been disabled.') +} +catch { + Write-Output -InputObject ('Failed - The specified guest accounts have not been disabled.') +} diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkEnableGuestAccounts.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkEnableGuestAccounts.ps1 new file mode 100644 index 0000000..bcaa715 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkEnableGuestAccounts.ps1 @@ -0,0 +1,24 @@ +# Script to bulk enable guest accounts in Azure AD, either all or for a specific domain +# + +# Are we disabling for a specific guest domain? Leave blank for all guests. +$guestDomain = '' + +# Install the AzureAD module, uncomment if required +#Install-Module -Name AzureAD + +# Import the AzureAD module and connect to Azure AD +Import-Module -Name AzureAD +Connect-AzureAD + +# Get a list of all guests from Azure AD either matching the domain or all guests +if ($guestDomain -ne '') { + $guestAccounts = Get-AzureADUser -All $true | Where-Object { $_.AccountEnabled -eq $false -and $_.UserType -eq 'Guest' -and $_.Mail -like ('*' + $guestDomain) } +} +else { + $guestAccounts = Get-AzureADUser -All $true | Where-Object { $_.AccountEnabled -eq $false -and $_.UserType -eq 'Guest' } +} + +# Enable the guest accounts +$guestAccounts | Set-AzureADUser -AccountEnabled $true +Write-Output -InputObject ('The specified guest accounts have been disabled.') diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkRemoveGuestsWithUnacceptedInvites.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkRemoveGuestsWithUnacceptedInvites.ps1 new file mode 100644 index 0000000..f31e87d --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkRemoveGuestsWithUnacceptedInvites.ps1 @@ -0,0 +1,21 @@ +# Find all guests with unaccepted invites over a specific time period and remove them +# + +# How many days are we allowing for invites to be accepted? (This can be 0 for all) +$cutOffDays = 30 + +# Install the AzureAD module, uncomment if required +#Install-Module -Name AzureAD + +# Import the AzureAD module and connect to Azure AD +Import-Module -Name AzureAD +Connect-AzureAD + +# Get the cut off date +$cutOffDate = (Get-Date).AddDays(-$cutOffDays) + +# Get a list of all guests with unaccepted invites older than the specificed timeframe +$unacceptedGuests = Get-AzureADUser -All $true | Where-Object { $_.UserType -eq 'Guest' -and $_.UserState -eq 'PendingAcceptance' -and $_.RefreshTokensValidFromDateTime -lt $cutOffDate } + +# Remove the guest accounts +$unacceptedGuests | Remove-AzureADUser diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkRemoveLicences.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkRemoveLicences.ps1 new file mode 100644 index 0000000..5d441cd --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkRemoveLicences.ps1 @@ -0,0 +1,44 @@ +# Bulk remove licences to a list of users. +# +# List of available SKUs can be obtained with (Get-AzureADSubscribedSku).SkuPartNumber +# + +# Where is the list of user UPN's? +$userListPath = 'C:\Temp\UserList.txt' + +# What licences are we removing? +$licencesToRemove = @('ENTERPRISEPACK','ATP_ENTERPRISE','EMSPREMIUM') + +# Import AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Import list of users from file +$userList = Get-Content -Path $userListPath | Sort-Object + +# Create a licenses object +$licenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses + +# Get SkuIDs for licence(s) to be removed +$licenses.RemoveLicenses = (Get-AzureADSubscribedSku | Where-Object {$_.SkuPartNumber -in $licencesToRemove}).SkuId + +# Remove the licenses +foreach ($username in $userList) { + try { + $user = Get-AzureADUser -ObjectId $username -ErrorAction Stop + if ($user.AccountEnabled -eq $true) { + Set-AzureADUserLicense -ObjectId $user.UserPrincipalName -AssignedLicenses $licenses + Write-Output -InputObject ('Licence(s) removed from user account ' + $user.UserPrincipalName + '.') + } + else { + Write-Output -InputObject ('User account ' + $user.UserPrincipalName + ' is disabled.') + } + } + catch { + Write-Output -InputObject ('There was a problem updating licences for user account ' + $user.UserPrincipalName + '.') + Write-Output -InputObject $Error[0] + } +} + +# Disconnect from AzureAD +Disconnect-AzureAD diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/BulkReplaceLicences.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/BulkReplaceLicences.ps1 new file mode 100644 index 0000000..dd415b6 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/BulkReplaceLicences.ps1 @@ -0,0 +1,59 @@ +# Bulk replace licences to a list of users. +# +# List of available SKUs can be obtained with (Get-AzureADSubscribedSku).SkuPartNumber +# + +# Where is the list of user UPN's? +$userListPath = 'C:\Temp\UserList.txt' + +# What licences are we adding? +$licencesToAdd = @('EMSPREMIUM') + +# What licences are we removing? +$licencesToRemove = @('EMS','AAD_PREMIUM_P2') + +# Import AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Import list of users from file +$userList = Get-Content -Path $userListPath | Sort-Object + +$userList = @('OAndrewsAdmin@sis.tv') + +# Get all available licence skus +$newSkuIDs = (Get-AzureADSubscribedSku | Where-Object {$_.SkuPartNumber -in $licencesToAdd}).SkuId + +# Create a licenses object +$licenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses + +# Add the licences to add to the licences object +foreach ($newSkuID in $newSkuIDs) { + $newLicense = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicense + $newLicense.SkuId = $newSkuID + $licenses.AddLicenses += $newLicense +} + +# Add the licences we want to remove to the $licenses object +$licenses.RemoveLicenses = (Get-AzureADSubscribedSku | Where-Object {$_.SkuPartNumber -in $licencesToRemove}).SkuID + +# Replace the licenses +foreach ($username in $userList) { + try { + $user = Get-AzureADUser -ObjectId $username -ErrorAction Stop + if ($user.AccountEnabled -eq $true) { + Set-AzureADUserLicense -ObjectId $user.UserPrincipalName -AssignedLicenses $licenses + Write-Output -InputObject ('Licences updated for user account ' + $user.UserPrincipalName + '.') + } + else { + Write-Output -InputObject ('User account ' + $user.UserPrincipalName + ' is disabled.') + } + } + catch { + Write-Output -InputObject ('There was a problem updating licences for user account ' + $user.UserPrincipalName + '.') + Write-Output -InputObject $Error[0] + } +} + +# Disconnect from AzureAD +Disconnect-AzureAD diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/FixOnlineUserUPN.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/FixOnlineUserUPN.ps1 new file mode 100644 index 0000000..a66ab8b --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/FixOnlineUserUPN.ps1 @@ -0,0 +1,14 @@ +# Update Online User UPN - when AD sync doesn't do it. + +# Import the Azure AD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Whose UPN are we changing? +$oldUPN = Read-Host -Prompt 'Enter user''s old UPN in the format username@domain' + +# What are we changing it to? +$newUPN = Read-Host -Prompt 'Enter user''s new UPN in the format username@domain' + +# Update the UPN in AzureAD +Set-AzureADUser -ObjectId $oldUPN -UserPrincipalName $newUPN diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/GetADGUIDFromAzureAD.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/GetADGUIDFromAzureAD.ps1 new file mode 100644 index 0000000..cea821e --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/GetADGUIDFromAzureAD.ps1 @@ -0,0 +1,10 @@ +# Import the Azure AD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Whose ID are we getting? +$userUPN = Read-Host -Prompt 'Enter user''s UPN in the format username@domain' + +# Convert 365 ImmutableID to AD GUID +$immutableID = (Get-AzureADUser -ObjectId $userUPN).ImmutableID +[GUID][System.Convert]::FromBase64String($immutableID) diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/GetLicencesAllUsers.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/GetLicencesAllUsers.ps1 new file mode 100644 index 0000000..87f23d7 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/GetLicencesAllUsers.ps1 @@ -0,0 +1,29 @@ +# Retrieve licences for all users and export to CSV. +# + +# Import AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Get all available licence details +$allSkus = Get-AzureADSubscribedSku + +# Import list of users from file +$users = Get-AzureADUser -All $true + +# Get Licences for each user and find out what they are from the list +$allUserLicences = @() +foreach ($user in $users) { + $assignedLicences = @() + foreach ($license in $user.AssignedLicenses.SkuID) { + $assignedLicences += ($allSkus | Where-Object { $_.SkuID -eq $license }).SkuPartNumber + } + $userLicences = [PSCustomObject]@{ + 'UserName' = $user.UserPrincipalName + 'AssignedLicences' = (($assignedLicences | Sort-Object) -join ';') + } + $allUserLicences += $userLicences +} + +# Export list to CSV file +$allUserLicences | Export-Csv -Path 'C:\Temp\AllUserLicences.csv' -NoTypeInformation diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/GetLicencesForUserList.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/GetLicencesForUserList.ps1 new file mode 100644 index 0000000..84a1c54 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/GetLicencesForUserList.ps1 @@ -0,0 +1,38 @@ +# Retrieve licences for a list of users and export them to a CSV file. +# + +# Where is the list of user UPN's? +$userListPath = 'C:\Temp\UserList.txt' + +# Import AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Get all available licence details +$allSkus = Get-AzureADSubscribedSku + +# Import list of users from file +$users = Get-Content -Path $userListPath | Sort-Object + +# Get Licences for user and find out what they are from the list +$allUserLicences = @() +foreach ($user in $users) { + $assignedLicences = @() + try { + $userDetails = Get-AzureADUser -ObjectId $user -ErrorAction Stop + foreach ($license in $userDetails.AssignedLicenses.SkuID) { + $assignedLicences += ($allSkus | Where-Object { $_.SkuID -eq $license }).SkuPartNumber + } + } + catch { + $assignedLicences = 'User not found.' + } + $userLicences = [PSCustomObject]@{ + 'UserName' = $user + 'AssignedLicences' = (($assignedLicences | Sort-Object) -join ';') + } + $allUserLicences += $userLicences +} + +# Export list to CSV file +$allUserLicences | Export-Csv -Path 'C:\Temp\UserLicences.csv' -NoTypeInformation diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/GetUsersFromPlanID.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/GetUsersFromPlanID.ps1 new file mode 100644 index 0000000..d7acf5a --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/GetUsersFromPlanID.ps1 @@ -0,0 +1,84 @@ +# Some example scripts for finding users with specific plans assigned +# +# A full list of subscription and plan ID's is available from: +# https://docs.microsoft.com/en-us/azure/active-directory/users-groups-roles/licensing-service-plan-reference +# +# Here I'm using the following plan IDs. +# +# OFFICESUBSCRIPTION (43de0ff5-c92c-492b-9116-175376d08c38) +# PROJECT_CLIENT_SUBSCRIPTION (fafd7243-e5c1-4a3a-9e40-495efcb1d3c3) +# VISIO_CLIENT_SUBSCRIPTION (663a804f-1c30-4ff0-9915-9db84f0d1cea) +# + +# Plan ID's to check for +$planID1 = '43de0ff5-c92c-492b-9116-175376d08c38' +$planID2 = 'fafd7243-e5c1-4a3a-9e40-495efcb1d3c3' +$planID3 = '663a804f-1c30-4ff0-9915-9db84f0d1cea' + +# Import the AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Get all users from AzureAD +$allUsers = Get-AzureADUser -All $true + +# Create variables to put the users in to +$planID1Users = @() +$planID2Users = @() +$planID3Users = @() + +# Check through the users and check what plans are assigned and enabled +foreach ($user in $allUsers) { + foreach ($assignedPlan in $user.AssignedPlans) { + # Find all users of plan 1 and add to the related variable + if ($assignedPlan.ServicePlanId -eq $planID1 -and $assignedPlan.CapabilityStatus -eq 'Enabled') { + $planID1Users += $user + } + # Find all users of plan 2 and add to the related variable + if ($assignedPlan.ServicePlanId -eq $planID2 -and $assignedPlan.CapabilityStatus -eq 'Enabled') { + $planID2Users += $user + } + # Find all users of plan 3 and add to the related variable + if ($assignedPlan.ServicePlanId -eq $planID3 -and $assignedPlan.CapabilityStatus -eq 'Enabled') { + $planID3Users += $user + } + } +} + +# Create variables to put the users in to +$plan1OnlyUsers = @() +$planID1and2Users = @() +$planID1and3Users = @() +$planID12and3Users = @() + +# Using plan 1 as the master list, check which other licences are assigned +foreach ($planID1User in $planID1Users) { + # Find users who are only in the plan 1 list + if ($planID1User -notin $planID2Users -and $planID1User -notin $planID3Users) { + $plan1OnlyUsers += $planID1User + } + # Find users who are the plan 1 and plan 2 list + if ($planID1User -in $planID2Users) { + $planID1and2Users += $planID1User + } + # Find users who are in the plan 1 and plan 3 list + if ($planID1User -in $planID3Users) { + $planID1and3Users += $planID1User + } + # Find users who are in all three lists + if ($planID1User -in $planID2Users -and $planID1User -in $planID3Users) { + $planID12and3Users += $planID1User + } +} + +# How many people in each list? +$plan1OnlyUsers.Count +$planID1and2Users.Count +$planID1and3Users.Count +$planID12and3Users.Count + +# Who are those people? +$plan1OnlyUsers +$planID1and2Users +$planID1and3Users +$planID12and3Users diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/InviteGuestAndAddToGroup.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/InviteGuestAndAddToGroup.ps1 new file mode 100644 index 0000000..70e3afd --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/InviteGuestAndAddToGroup.ps1 @@ -0,0 +1,36 @@ +# Script to invite a list of guest users to AzureAD and add them to a group +# +# Useful for bulk adding guests to a SharePoint or Teams group +# +# Uses a CSV file containing columns for FirstName,LastName,DisplayName,ExternalEmailAddress +# + +# Where is our list of people? +$contactsFile = 'C:\Temp\ExternalContacts.csv' + +# What group are we added them to? +$groupName = 'Test Group' + +# Import the AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Import the list of people +$contactsList = Import-Csv -Path $contactsFile + +# Find the group ID for our group +$groupID = (Get-AzureADGroup -All $true | Where-Object {$_.DisplayName -eq $groupName}).ObjectId + +# Run through the list sending the guest invite and adding them to the group, unless their email address is already used somewhere +foreach ($externalUser in $contactsList) { + $getExisting = Get-AzureADUser -SearchString $externalUser.ExternalEmailAddress + + if ($getExisting.Count -eq 0) { + $newUser = New-AzureADMSInvitation -InvitedUserDisplayName $externalUser.DisplayName -InvitedUserEmailAddress $externalUser.ExternalEmailAddress -SendInvitationMessage $true -InviteRedirectUrl "https://myapps.microsoft.com" + Add-AzureADGroupMember -ObjectId $groupID -RefObjectId $newUser.InvitedUser.Id + Write-Output -InputObject ('Guest ' + $externalUser.ExternalEmailAddress + ' created and added to group.') + } + else { + Write-Output -InputObject ('Object already exists with email address ' + $externalUser.ExternalEmailAddress + '.') + } +} diff --git a/Powershell/PowerShell-Office365Admin/AzureAD/RemoveAllLicencesFromUserList.ps1 b/Powershell/PowerShell-Office365Admin/AzureAD/RemoveAllLicencesFromUserList.ps1 new file mode 100644 index 0000000..b29be56 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/AzureAD/RemoveAllLicencesFromUserList.ps1 @@ -0,0 +1,42 @@ +# Remove all licences from a list of users +# +# Removing licences with this module doesn't work in the way that Microsoft's documentation states. +# I'm assuming this is a bug, so the code below works at time of creation but may stop working in the future. +# + +# Where is the list of user UPN's? +$userListPath = 'C:\Temp\UserList.txt' + +# Import AzureAD module and connect +Import-Module AzureAD +Connect-AzureAD + +# Import list of users from file +$userList = Get-Content -Path $userListPath | Sort-Object + +# Remove all the licences +foreach ($username in $userList) { + try { + $user = Get-AzureADUser -ObjectId $username -ErrorAction Stop + if ($user.AccountEnabled -eq $true) { + if(($user.AssignedLicenses.SkuId).Count -ge 1) { + $licenses = New-Object -TypeName Microsoft.Open.AzureAD.Model.AssignedLicenses + $licenses.RemoveLicenses = (Get-AzureADSubscribedSku | Where-Object {$_.SkuId -in $user.AssignedLicenses.SkuId}).SkuId + Set-AzureADUserLicense -ObjectId $user.UserPrincipalName -AssignedLicenses $licenses + Write-Output -InputObject ('All licences removed from user account ' + $username + '.') + } + else { + Write-Output -InputObject ('User account ' + $username + ' has no licences assigned.') + } + } + else { + Write-Output -InputObject ('User account ' + $username + ' is disabled.') + } + } + catch { + Write-Output -InputObject ('User account ' + $username + ' does not exist.') + } +} + +# Disconnect from AzureAD +Disconnect-AzureAD diff --git a/Powershell/PowerShell-Office365Admin/Exchange/CheckMailboxStatsAccessAndPermissions.ps1 b/Powershell/PowerShell-Office365Admin/Exchange/CheckMailboxStatsAccessAndPermissions.ps1 new file mode 100644 index 0000000..f42e6f6 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/Exchange/CheckMailboxStatsAccessAndPermissions.ps1 @@ -0,0 +1,63 @@ +# Script to get details for a list of mailboxes and save that out to a CSV file +# + +# File containing the list of mailboxes +$inputFile = 'C:\Temp\MailboxList.txt' + +# File to save the results to +$outputFile = 'C:\Temp\SharedMailboxes.csv' + +# Establish a session to Exchange Online +$credentials = Get-Credential -Message 'Enter your Exchange Online administrator credentials' +$connectionParams = @{ + 'ConfigurationName' = 'Microsoft.Exchange'; + 'ConnectionUri' = 'https://outlook.office365.com/powershell-liveid/'; + 'Credential' = $credentials; + 'Authentication' = 'Basic'; + 'AllowRedirection' = $true +} +$exchangeSession = New-PSSession @connectionParams +Import-PSSession -Session $exchangeSession + +# Check output folder exists and create it if it doesn't +$outputPath = (Split-Path -Path $outputFile) +if (!(Test-Path -Path $outputPath)) {New-Item -Path $outputFolder -ItemType Directory} + +# If output file already exists, delete it. +if (Test-Path -Path $outputFile) {Remove-Item -Path $outputFile} + +# Get the list of mailboxes from the file +$mailboxes = Get-Content -Path $inputFile + +# Initialise the results table +$mailboxesTable = @() + +# Iterate through the mailboxes from the file and show a progress bar as we go. +foreach ($mailbox in $mailboxes) { + Write-Progress -Activity 'Checking..' -status $mailbox -percentComplete ($mailboxes.IndexOf($mailbox) / $mailboxes.Count * 100) + + # Get the statistics for the mailbox. + $mailboxStats = '' + $mailboxStats = Get-MailboxStatistics -Identity $mailbox -ErrorAction SilentlyContinue - + + # If mailboxStats is blank then mailbox doesn't exist, so that entry can be skipped. For all others get the mailbox permissions and build the output table. + if ($mailboxStats -ne $null) { + # Get permit permissions for users where the username has an @ in it, this filters out all the system permissions. + $usersWithAccess = (Get-MailboxPermission -Identity $mailbox | Where-Object -Property {($_.User -like '*@*') -and ($_.Deny -ne 'False')}).User -join '; ' + + $tableRow = New-Object System.Object + $tableRow | Add-Member -MemberType NoteProperty -Name 'MailboxUPN' -Value $mailbox + $tableRow | Add-Member -MemberType NoteProperty -Name 'MailboxType' -Value $mailboxStats.MailboxTypeDetail + $tableRow | Add-Member -MemberType NoteProperty -Name 'ItemCount' -Value $mailboxStats.ItemCount + $tableRow | Add-Member -MemberType NoteProperty -Name 'TotalItemSize' -Value $mailboxStats.TotalItemSize + $tableRow | Add-Member -MemberType NoteProperty -Name 'LastLogonTime' -Value $mailboxStats.LastLogonTime + $tableRow | Add-Member -MemberType NoteProperty -Name 'UsersWithAccess' -Value $usersWithAccess + $mailboxesTable += $tableRow + } +} + +# Output the final table of results to a file. +$mailboxesTable | Export-Csv -Path $outputFile -NoTypeInformation + +# End the Exchange Online session +Remove-PSSession -Session $exchangeSession diff --git a/Powershell/PowerShell-Office365Admin/Exchange/FindUsersWithMismatchedDomains.ps1 b/Powershell/PowerShell-Office365Admin/Exchange/FindUsersWithMismatchedDomains.ps1 new file mode 100644 index 0000000..243b223 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/Exchange/FindUsersWithMismatchedDomains.ps1 @@ -0,0 +1,20 @@ +# Find mailboxes where UPN domain doesn't match email domain +# + +# Establish a session to Exchange Online +$credentials = Get-Credential -Message 'Enter your Exchange Online administrator credentials' +$connectionParams = @{ + 'ConfigurationName' = 'Microsoft.Exchange'; + 'ConnectionUri' = 'https://outlook.office365.com/powershell-liveid/'; + 'Credential' = $credentials; + 'Authentication' = 'Basic'; + 'AllowRedirection' = $true +} +$exchangeSession = New-PSSession @connectionParams +Import-PSSession -Session $exchangeSession + +# Get list of mailboxes with a different mail domain to UPN domain +Get-Mailbox -ResultSize Unlimited | Where-Object {$_.UserPrincipalName.Split('@')[1] -ne $_.PrimarySmtpAddress.Split('@')[1]} | Format-Table Name,UserPrincipalName,PrimarySmtpAddress,RecipientTypeDetails + +# Disconnect from Exchange Online +Remove-PSSession $exchangeSession diff --git a/Powershell/PowerShell-Office365Admin/Exchange/GetAllForwardingRules.ps1 b/Powershell/PowerShell-Office365Admin/Exchange/GetAllForwardingRules.ps1 new file mode 100644 index 0000000..fc9a0d2 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/Exchange/GetAllForwardingRules.ps1 @@ -0,0 +1,38 @@ +# Script to get all client forwarding rules, smtp forwarding rules and delegates on mailboxes +# +# This builds on top of a script from https://github.com/OfficeDev/O365-InvestigationTooling +# + +# Establish a session to Exchange Online +$credentials = Get-Credential -Message 'Enter your Exchange Online administrator credentials' +$connectionParams = @{ + 'ConfigurationName' = 'Microsoft.Exchange'; + 'ConnectionUri' = 'https://outlook.office365.com/powershell-liveid/'; + 'Credential' = $credentials; + 'Authentication' = 'Basic'; + 'AllowRedirection' = $true +} +$exchangeSession = New-PSSession @connectionParams +Import-PSSession -Session $exchangeSession + +$allUsers = @() +$allUsers = Get-Mailbox -ResultSize Unlimited | Select-Object DisplayName,UserPrincipalName,ForwardingAddress,ForwardingSMTPAddress,DeliverToMailboxandForward + +$userInboxRules = @() +$userDelegates = @() + +foreach ($user in $allUsers) { + Write-Progress -Activity "Checking inbox rules for..." -status $user.UserPrincipalName -percentComplete ($allUsers.IndexOf($user) / $allUsers.Count * 100) + $userInboxRules += Get-InboxRule -Mailbox $user.UserPrincipalName | ` + Select-Object MailboxOwnerId,Name,Description,Enabled,Priority,ForwardTo,ForwardAsAttachmentTo,RedirectTo,DeleteMessage | ` + Where-Object {($_.ForwardTo -ne $null) -or ($_.ForwardAsAttachmentTo -ne $null) -or ($_.RedirectsTo -ne $null)} + $userDelegates += Get-MailboxPermission -Identity $user.UserPrincipalName | Where-Object {($_.IsInherited -ne "True") -and ($_.User -notlike "*SELF*")} +} + +$smtpForwarding = $allUsers | Select-Object DisplayName,ForwardingAddress,ForwardingSMTPAddress,DeliverToMailboxandForward | Where-Object {$_.ForwardingSMTPAddress -ne $null} + +$userInboxRules | Export-Csv MailForwardingRulesToExternalDomains.csv -NoTypeInformation +$smtpForwarding | Export-Csv Mailboxsmtpforwarding.csv -NoTypeInformation +$userDelegates | Export-Csv MailboxDelegatePermissions.csv -NoTypeInformation + +Remove-PSSession -Session $exchangeSession diff --git a/Powershell/PowerShell-Office365Admin/Exchange/GrantCalendarDelegateAccess.ps1 b/Powershell/PowerShell-Office365Admin/Exchange/GrantCalendarDelegateAccess.ps1 new file mode 100644 index 0000000..8ae8e83 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/Exchange/GrantCalendarDelegateAccess.ps1 @@ -0,0 +1,41 @@ +# Script to grant access rights on mailboxes +# + +# Mailboxes to grant rights on +$grantRightsOnMailboxes = @('','') + +# Users to grant rights to +$grantRightsToUsers = @('','') + +# Rights to grant +$accessRights = 'Editor' + +# Establish a session to Exchange Online +$credentials = Get-Credential -Message 'Enter your Exchange Online administrator credentials' +$connectionParams = @{ + 'ConfigurationName' = 'Microsoft.Exchange'; + 'ConnectionUri' = 'https://outlook.office365.com/powershell-liveid/'; + 'Credential' = $credentials; + 'Authentication' = 'Basic'; + 'AllowRedirection' = $true +} +$exchangeSession = New-PSSession @connectionParams +Import-PSSession -Session $exchangeSession + +# Apply the permissions +foreach ($grantRightsToUser in $grantRightsToUsers ) { + foreach ($grantRightsOnMailbox in $grantRightsOnMailboxes) { + $calendarIdentity = $grantRightsOnMailbox + ':\Calendar' + $existingPermissions = Get-MailboxFolderPermission -Identity $calendarIdentity -User $grantRightsToUser -ErrorAction SilentlyContinue + if (!($existingPermissions)) { + Add-MailboxFolderPermission -Identity $calendarIdentity -User $grantRightsToUser -AccessRights $accessRights + } + else { + Set-MailboxFolderPermission -Identity $calendarIdentity -User $grantRightsToUser -AccessRights $accessRights + } + Set-Mailbox -Identity $upn –GrantSendOnBehalfTo @{add=$editor} + } +} + +# End the PowerShell session +Remove-PSSession -Session $exchangeSession diff --git a/Powershell/PowerShell-Office365Admin/Exchange/LockdownMailbox.ps1 b/Powershell/PowerShell-Office365Admin/Exchange/LockdownMailbox.ps1 new file mode 100644 index 0000000..f68d2f9 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/Exchange/LockdownMailbox.ps1 @@ -0,0 +1,45 @@ +# Enable mailbox auditing and disable PowerShell remoting on individual mailboxes +# +# Working on this as a one stop for hardening Exchange Online accounts +# + +# UPN of New User +$newUPN = '' + +# Is the user an administrator? +$isAnAdmin = $false + +# Establish a session to Exchange Online +$credentials = Get-Credential -Message 'Enter your Exchange Online administrator credentials' +$connectionParams = @{ + 'ConfigurationName' = 'Microsoft.Exchange'; + 'ConnectionUri' = 'https://outlook.office365.com/powershell-liveid/'; + 'Credential' = $credentials; + 'Authentication' = 'Basic'; + 'AllowRedirection' = $true +} +$exchangeSession = New-PSSession @connectionParams +Import-PSSession -Session $exchangeSession + +# Set Auditing parameters +$params = @{ + 'AuditEnabled' = $true + 'AuditLogAgeLimit' = '180' + 'AuditAdmin' = @('Update','MoveToDeletedItems','SoftDelete','HardDelete','SendAs','SendOnBehalf','Create','UpdateFolderPermission') + 'AuditDelegate' = @('Update','SoftDelete','HardDelete','SendAs','Create','UpdateFolderPermissions','MoveToDeletedItems','SendOnBehalf') + 'AuditOwner' = @('UpdateFolderPermission','MailboxLogin','Create','SoftDelete','HardDelete','Update','MoveToDeletedItems') +} + +# Enable Auditing +Get-Mailbox -Identity $newUPN | Set-Mailbox @params + +# Disable PowerShell Remoting for non-Admin staff +if ($isAnAdmin) { + Set-User -Identity $newUPN -RemotePowerShellEnabled $true +} +else { + Set-User -Identity $newUPN -RemotePowerShellEnabled $false +} + +# Disconnect from Exchange Online +Remove-PSSession $exchangeSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/BulkRemoveProxyAddressesRemote.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/BulkRemoveProxyAddressesRemote.ps1 new file mode 100644 index 0000000..8fa67f4 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/BulkRemoveProxyAddressesRemote.ps1 @@ -0,0 +1,111 @@ +# Script to bulk remove email proxy addresses from Exchange users in a synced environment using an on-prem Exchange management server +# + +# What is the FQDN of the on-prem Exchange server? +$exchangeServerFQDN = '' + +# Which domains are we removing? +$domainsToRemove = @('','') + +# Create Exchange connection Uri from FQDN +$exchangeConnectionUri = 'http://' + $exchangeServerFQDN +'/PowerShell/' + +# Establish a session to Exchange +$userCredential = Get-Credential +$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $exchangeConnectionUri -Authentication Kerberos -Credential $userCredential +Import-PSSession $session -DisableNameChecking + +### Check if address policies are using this domain ### + +# Initialise a hastable to store our results in +$addressPolicies = @() + +# Get all address policies from Exchange +$allAddressPolicies = Get-EmailAddressPolicy + +# Run through the domains checking if the domain to be removed is in the address policies +foreach ($domainToRemove in $domainsToRemove) { + $emailAddressTemplate = 'SMTP:@' + $domainToRemove + $addressPolicies += $allAddressPolicies | Where-Object {$_.EnabledEmailAddressTemplates -contains $emailAddressTemplate} +} + +# If domain found in address policies then list them and ask if we want to contiue removing the proxy domain +if ($addressPolicies.Count -gt 0) { + Write-Output -InputObject ('The following address policies are using the domain to be removed:') + $addressPolicies | Format-Table + $continue = '' + while ($continue -notmatch '[YyNn]') { + $continue = Read-Host -Prompt 'Do you want to continue running the script? (Y/N)' + } + if ($continue -match '[Nn]') { + Write-Output -InputObject ('Terminating script.') + break + } + else { + Write-Output -InputObject ('Continuing with script.') + } +} + +### + +### Remove the domain from mailboxes ### + +# Get All Mailboxes +$allMailboxes = Get-RemoteMailbox -ResultSize Unlimited | Sort-Object -Property alias + +# Remove alias from each mailbox +foreach ($mailbox in $allMailboxes) { + $redundantAddresses = @() + foreach ($domainToRemove in $domainsToRemove) { + $redundantAddresses += (($mailbox.EmailAddresses -split ',' | Where-Object {$_ -match $domainToRemove}) -replace 'smtp:','') + } + if ($redundantAddresses.Count -gt 0) { + Write-Output -InputObject ('Removing addresses ' + $redundantAddresses + ' from maibox ' + $mailbox.Name) + Set-RemoteMailbox -Identity $mailbox.Identity -EmailAddresses @{remove=$redundantAddresses} -Confirm:$false + } +} + +### + +### Remove the domain from contacts ### + +# Get all the contacts +$allContacts = Get-MailContact -ResultSize Unlimited | Sort-Object -Property alias + +# Remove alias from each contact +foreach ($contact in $allContacts) { + $redundantAddresses = @() + foreach ($domainToRemove in $domainsToRemove) { + $redundantAddresses += (($contact.EmailAddresses -split ',' | Where-Object {$_ -like ('*' + $domainToRemove + '*')}) -replace 'smtp:','') + } + if ($redundantAddresses.Count -gt 0) { + Write-Output -InputObject ('Removing addresses ' + $redundantAddresses + ' from contact ' + $contact.Name) + Set-MailContact -Identity $contact.Identity -EmailAddresses @{remove=$redundantAddresses} -Confirm:$false -ForceUpgrade:$true + } +} + +### + +### Remove the domain from groups ### + +# Get all the groups (this includes email enabled security groups) +$allGroups = Get-DistributionGroup -ResultSize Unlimited | Sort-Object -Property alias + +# Remove alias from each group +foreach ($group in $allGroups) { + $redundantAddresses = @() + foreach ($domainToRemove in $domainsToRemove) { + $redundantAddresses += (($group.EmailAddresses -split ',' | Where-Object {$_ -like ('*' + $domainToRemove + '*')}) -replace 'smtp:','') + } + if ($redundantAddresses.Count -gt 0) { + Write-Output -InputObject ('Removing addresses ' + $redundantAddresses + ' from group ' + $group.Name) + Set-DistributionGroup -Identity $group.Identity -EmailAddresses @{remove=$redundantAddresses} -Confirm:$false + } +} + +### + +### Public folders don't feature here because in this scenario they're cloud only ### + +# End the Exchange Session +Remove-PSSession -Session $session diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/CompareRemoteMailboxesToO365.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/CompareRemoteMailboxesToO365.ps1 new file mode 100644 index 0000000..93f958c --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/CompareRemoteMailboxesToO365.ps1 @@ -0,0 +1,62 @@ +# Find mailboxes for synced accounts, where the mailbox exists in Exchange Online but doesn't exist on-prem as a remote mailbox. +# +# Like the other stuff in this folder, it's a bit of a niche scenario. +# We're looking for mailboxes which were created in on-prem AD and then licenced in the cloud without a remote mailbox being created on the on-prem Exchange server, so that we can remote mail enable them correctly. +# +# This is a bit complicated as it requires connected to two Exchange environments at once, so uses command prefixes for one of them. +# + +# What is the FQDN of the on-prem Exchange server? +$exchangeServerFQDN = '' + +# What is your remote routing address? E.g.: @domain.mail.onmicrosoft.com +$remoteRoutingSuffix = '@domain.mail.onmicrosoft.com' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Create Exchange on-prem connection Uri from FQDN +$exchangeConnectionUri = 'http://' + $exchangeServerFQDN +'/PowerShell/' + +# Establish a session to Exchange on-prem and add the OnPrem prefix to all commands +$userCredential = Get-Credential +$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $exchangeConnectionUri -Authentication Kerberos -Credential $userCredential +Import-PSSession $session -DisableNameChecking -Prefix OnPrem + +# Get list of mailboxes from Exchange online for synced users +$allOnlineMailboxes = Get-Mailbox -ResultSize Unlimited | Where-Object {$_.IsDirSynced -eq $true -and $_.Name -notlike 'DiscoverySearchMailbox*'} + +# Get list of remote mailboxes from on-prem server +$allOnPremMailboxes = Get-OnPremRemoteMailbox -ResultSize Unlimited + +# Compare the two lists and add those missing from the on-prem list to the $syncedMailboxMismatch hashtable +$syncedMailboxMismatch = $allOnlineMailboxes | Where-Object {$allOnPremMailboxes.PrimarySmtpAddress -notcontains $_.PrimarySmtpAddress} + +# Find mailboxes where alias and username match +$matchedUPNAliases = $syncedMailboxMismatch | Where-Object {$_.Alias -eq $_.UserPrincipalName.Split('@')[0]} + +# Find mailboxes where alias and username don't match +$mismatchedUPNAliases = $syncedMailboxMismatch | Where-Object {$_.Alias -ne $_.UserPrincipalName.Split('@')[0]} + +# Fix the mailboxes where username and alias matched. +foreach ($mailboxToRemoteEnable in $matchedUPNAliases) { + $mailboxUsername = $mailboxToRemoteEnable.UserPrincipalName.Split('@')[0] + $mailboxToFix = $mailboxToRemoteEnable.UserPrincipalName + $remoteRoutingAddress = $mailboxUsername + $remoteRoutingSuffix + Enable-OnPremRemoteMailbox -Identity $mailboxToFix -RemoteRoutingAddress $remoteRoutingAddress +} + +# Write out the mailboxes that have been updated +Write-Output -InputObject ('The following mailboxes have been remote mail enabled.') +$matchedUPNAliases | Select-Object Name,Alias,UserPrincipalName,PrimarySmtpAddress + +# Write out the mailboxes that have been left due to a mismatch between username and alias +Write-Output -InputObject ('The following mailboxes have not been changed because they have a mismatch between email alias and username.') +$mismatchedUPNAliases | Select-Object Name,Alias,UserPrincipalName,PrimarySmtpAddress + +# End the Exchange Session +Remove-PSSession -Session $session diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/DisableRemoteMailUser.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/DisableRemoteMailUser.ps1 new file mode 100644 index 0000000..3905d3c --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/DisableRemoteMailUser.ps1 @@ -0,0 +1,24 @@ +# Disable a list of mail users +# + +# What is the FQDN of the on-prem Exchange server? +$exchangeServerFQDN = '' + +# What accounts are we disabling? +$usersToDisable = @('','') + +# Create Exchange connection Uri from FQDN +$exchangeConnectionUri = 'http://' + $exchangeServerFQDN +'/PowerShell/' + +# Establish a session to Exchange +$userCredential = Get-Credential +$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $exchangeConnectionUri -Authentication Kerberos -Credential $userCredential +Import-PSSession $session -DisableNameChecking -AllowClobber + +# Get list of mailboxes +foreach ($userToDisable in $usersToDisable) { + Disable-RemoteMailbox -Identity $userToDisable -Confirm:$false +} + +# End the Exchange Session +Remove-PSSession -Session $session diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/GetMailboxesBasedOnPrimarySMTP.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/GetMailboxesBasedOnPrimarySMTP.ps1 new file mode 100644 index 0000000..72ba826 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/GetMailboxesBasedOnPrimarySMTP.ps1 @@ -0,0 +1,28 @@ +# Find mailboxes using a specific email domain and export list to CSV file +# + +# What is the FQDN of the on-prem Exchange server? +$exchangeServerFQDN = '' + +# Primary SMTP domain to search for +$primarySMTP = '' + +# Where are we saving the output file? +$outputFile = 'C:\Temp\Mailboxes.csv' + +# Create Exchange connection Uri from FQDN +$exchangeConnectionUri = 'http://' + $exchangeServerFQDN +'/PowerShell/' + +# Establish a session to Exchange +$userCredential = Get-Credential +$session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $exchangeConnectionUri -Authentication Kerberos -Credential $userCredential +Import-PSSession $session -DisableNameChecking + +# Get list of mailboxes +$allMailboxes = Get-RemoteMailbox -ResultSize Unlimited | Where-Object {($_.PrimarySmtpAddress.Split('@')[1] -eq $primarySMTP)} + +# Export results to CSV file +$allMailboxes | Select-Object Name,Alias,UserPrincipalName,PrimarySmtpAddress,EmailAddresses | Export-Csv -Path $outputFile -NoTypeInformation + +# End the Exchange Session +Remove-PSSession -Session $session diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/README.md b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/README.md new file mode 100644 index 0000000..7b93e96 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithAADConnect/README.md @@ -0,0 +1,15 @@ +# Exchange Online with AzureAD Connect + +## What is this? + +The scripts in this folder are for managing mailboxes in a synced environment, where you have an Exchange server on-prem purely for management purposes. This means all mailboxes are seen as "remote" mailboxes, so all the scripts use commands to that effect. These can easily be updated to a normal environment like on-prem only or cloud only just by removing the work "remote" from the commands. For example, Get-RemoteMailbox to just Get-Mailbox. + +## Pre-requisites + +These scripts require you to have on-prem Active Directory with an on-prem Exchange server for management, and using AzureAD Connect to sync to AzureAD. + +It's pretty niche. + +## Disclaimer + +All scripts are provided as is without warranty of any kind, use them at your own risk. diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/AddGuestsToGAL.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/AddGuestsToGAL.ps1 new file mode 100644 index 0000000..1e0f433 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/AddGuestsToGAL.ps1 @@ -0,0 +1,20 @@ +# Bulk change guest accounts from a certain domain so that they show in the Global Address List +# +# Uses the new PowerShell "module" that support MFA. +# + +# What domain are the guests email addresses from? +$guestDomain = '' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Find all the relevant users and enable them to show in the address list +Get-MailUser -ResultSize Unlimited | Where-Object {$_.RecipientTypeDetails -eq 'GuestMailUser' -and $_.EmailAddresses -match $guestDomain} | Set-MailUser -HiddenFromAddressListsEnabled $false + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/AddRoomCalendarEditors.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/AddRoomCalendarEditors.ps1 new file mode 100644 index 0000000..6ff2edc --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/AddRoomCalendarEditors.ps1 @@ -0,0 +1,42 @@ +# Create a group and add it to all room mailboxes as an editor +# +# Uses the new PowerShell "module" that support MFA. +# + +# What do you want the editors group to be called? +$editorsGroup = 'Calendar Editors' + +# Who do you want to be in the group? This can be 1 or more people. +$editorsMembers = @('','') + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get all room mailboxes in the organisation +$roomMailboxes = (Get-Mailbox -RecipientTypeDetails RoomMailbox).Alias + +# If the editors group doesn't exist, create it. +if (!(Get-DistributionGroup -Identity $editorsGroup -ErrorAction SilentlyContinue)) { + New-DistributionGroup -Name $editorsGroup -Type Security +} + +# Add members to the group +$existingMembers = Get-DistributionGroupMember -Identity $editorsGroup +foreach ($editorsMember in $editorsMembers) { + if ($editorsMember -notin $existingMembers.Name) { + Add-DistributionGroupMember -Identity $editorsGroup -Member $editorsMember + } +} + +# Add the permissions to the mailboxes +foreach ($roomMailbox in $roomMailboxes) { + $calendarFolder = $mailboxAlias + ':\calendar' + Add-MailboxFolderPermission -Identity $calendarFolder -User $editorsGroup -AccessRights Editor +} + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/BlockEmailForwardingToSpecificDomains.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/BlockEmailForwardingToSpecificDomains.ps1 new file mode 100644 index 0000000..6378208 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/BlockEmailForwardingToSpecificDomains.ps1 @@ -0,0 +1,41 @@ +# Create a rule to block email forwarding to specific domains. +# +# Uses the new PowerShell "module" that support MFA. +# + +# What domains are we blocking? +$domainListFile = 'C:\Temp\DomainList.txt' + +# What do we want to call the rule? +$ruleName = 'Block Auto Forwarding to Specific Domains 4' + +# What reason do we want end users to see for the rejection? +$rejectionReason = 'Auto forwarding messages to this email provider is not permitted.' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get the domain list from the file +$domainList = Get-Content -Path $domainListFile + +# Create a new rule +$parameters = @{ + 'Name' = $ruleName; + 'FromScope' = 'InOrganization'; + 'SenderAddressLocation' = 'Header' + 'RecipientDomainIs' = $domainList; + 'MessageTypeMatches' = 'AutoForward'; + 'RejectMessageEnhancedStatusCode' = '5.7.1' + 'RejectMessageReasonText' = $rejectionReason; + 'Priority' = 0; + 'Mode' = 'Enforce' + 'Enabled' = $true +} +New-TransportRule @parameters + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/BulkRemoveProxyAddresses.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/BulkRemoveProxyAddresses.ps1 new file mode 100644 index 0000000..b2a5c15 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/BulkRemoveProxyAddresses.ps1 @@ -0,0 +1,91 @@ +# Script to bulk remove email proxy addresses from Exchange Online users +# + +# Which domains are we removing? +$domainsToRemove = @('','') + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +### Remove the domain from mailboxes ### + +# Get All Mailboxes +$allMailboxes = Get-Mailbox -ResultSize Unlimited | Sort-Object -Property alias + +# Remove alias from each mailbox +foreach ($mailbox in $allMailboxes) { + $redundantAddresses = @() + foreach ($domainToRemove in $domainsToRemove) { + $redundantAddresses += (($mailbox.EmailAddresses -split ',' | Where-Object {$_ -like ('*' + $domainToRemove + '*')}) -replace 'smtp:','') + } + if ($redundantAddresses.Count -gt 0) { + Write-Output -InputObject ('Removing addresses ' + $redundantAddresses + ' from maibox ' + $mailbox.Name) + Set-Mailbox -Identity $mailbox.Identity -EmailAddresses @{remove=$redundantAddresses} -Confirm:$false + } +} + +### + +### Remove the domain from contacts ### + +# Get all the contacts +$allContacts = Get-MailContact -ResultSize Unlimited | Sort-Object -Property alias + +# Remove alias from each contact +foreach ($contact in $allContacts) { + $redundantAddresses = @() + foreach ($domainToRemove in $domainsToRemove) { + $redundantAddresses += (($contact.EmailAddresses -split ',' | Where-Object {$_ -like ('*' + $domainToRemove + '*')}) -replace 'smtp:','') + } + if ($redundantAddresses.Count -gt 0) { + Write-Output -InputObject ('Removing addresses ' + $redundantAddresses + ' from contact ' + $contact.Name) + Set-MailContact -Identity $contact.Identity -EmailAddresses @{remove=$redundantAddresses} -Confirm:$false -ForceUpgrade:$true + } +} + +### + +### Remove the domain from groups ### + +# Get all the groups (this includes email enabled security groups) +$allGroups = Get-DistributionGroup -ResultSize Unlimited | Sort-Object -Property alias + +# Remove alias from each group +foreach ($group in $allGroups) { + $redundantAddresses = @() + foreach ($domainToRemove in $domainsToRemove) { + $redundantAddresses += (($group.EmailAddresses -split ',' | Where-Object {$_ -like ('*' + $domainToRemove + '*')}) -replace 'smtp:','') + } + if ($redundantAddresses.Count -gt 0) { + Write-Output -InputObject ('Removing addresses ' + $redundantAddresses + ' from group ' + $group.Name) + Set-DistributionGroup -Identity $group.Identity -EmailAddresses @{remove=$redundantAddresses} -Confirm:$false + } +} + +### + +### Remove the domain from public folders ### + +# Get all the groups (this includes email enabled security groups) +$allPublicFolders = Get-MailPublicFolder -ResultSize Unlimited | Sort-Object -Property alias + +# Remove alias from each public folder +foreach ($publicFolder in $allPublicFolders) { + $redundantAddresses = @() + foreach ($domainToRemove in $domainsToRemove) { + $redundantAddresses += (($publicFolder.EmailAddresses -split ',' | Where-Object {$_ -like ('*' + $domainToRemove + '*')}) -replace 'smtp:','') + } + if ($redundantAddresses.Count -gt 0) { + Write-Output -InputObject ('Removing addresses ' + $redundantAddresses + ' from public folder ' + $publicFolder.Name) + Set-MailPublicFolder -Identity $publicFolder.Identity -EmailAddresses @{remove=$redundantAddresses} -Confirm:$false + } +} + +### + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/EnableExchangeModernAuth.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/EnableExchangeModernAuth.ps1 new file mode 100644 index 0000000..ff77cee --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/EnableExchangeModernAuth.ps1 @@ -0,0 +1,20 @@ +# Enable Modern Authentication in Exchange Online +# +# Uses the new PowerShell "module" that support MFA. +# + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Enable modern authentication +Set-OrganizationConfig -OAuth2ClientProfileEnabled $true + +# Verify the setting has changed +Get-OrganizationConfig | Format-Table -AutoSize Name,OAuth2ClientProfileEnabled + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/EnableMailboxAuditing.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/EnableMailboxAuditing.ps1 new file mode 100644 index 0000000..9d0ace6 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/EnableMailboxAuditing.ps1 @@ -0,0 +1,29 @@ +# Enable mailbox auditing on mailboxes where auditing is not already enabled +# +# This is a rewrite of a script from https://github.com/OfficeDev/O365-InvestigationTooling +# + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Set Auditing parameters +$params = @{ + 'AuditEnabled' = $true + 'AuditLogAgeLimit' = '180' + 'AuditAdmin' = @('Update','MoveToDeletedItems','SoftDelete','HardDelete','SendAs','SendOnBehalf','Create','UpdateFolderPermission') + 'AuditDelegate' = @('Update','SoftDelete','HardDelete','SendAs','Create','UpdateFolderPermissions','MoveToDeletedItems','SendOnBehalf') + 'AuditOwner' = @('UpdateFolderPermission','MailboxLogin','Create','SoftDelete','HardDelete','Update','MoveToDeletedItems') +} + +# Enable Auditing +Get-Mailbox -ResultSize Unlimited | Where-Object {$_.RecipientTypeDetails -match '(User|Shared|Room|Discovery)Mailbox' -and $_.AuditEnabled -eq $false} | Set-Mailbox @params + +# Check Auditing +Get-Mailbox -ResultSize Unlimited | Where-Object {$_.RecipientTypeDetails -match '(User|Shared|Room|Discovery)Mailbox'} | Format-Table -AutoSize UserPrincipalName,RecipientTypeDetails,AuditEnabled,AuditLogAgeLimit + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/FindUsersWithMismatchedDomains.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/FindUsersWithMismatchedDomains.ps1 new file mode 100644 index 0000000..e596e18 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/FindUsersWithMismatchedDomains.ps1 @@ -0,0 +1,15 @@ +# Find mailboxes where UPN domain doesn't match email domain +# + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get list of mailboxes with a different mail domain to UPN domain +Get-Mailbox -ResultSize Unlimited | Where-Object {$_.UserPrincipalName.Split('@')[1] -ne $_.PrimarySmtpAddress.Split('@')[1]} | Format-Table Name,UserPrincipalName,PrimarySmtpAddress,RecipientTypeDetails + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetDistributionGroupsAndMembers.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetDistributionGroupsAndMembers.ps1 new file mode 100644 index 0000000..8d5d6b5 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetDistributionGroupsAndMembers.ps1 @@ -0,0 +1,40 @@ +# Find shared mailboxes on the basis of their email domain and lists of who has access to them +# +# Uses the new PowerShell "module" that support MFA. +# + +# Where to save the CSV files to +$outputFile = 'C:\Temp\GroupDetails.csv' + +# Wildcard for groups to find +$searchWildcard = '*@example.domain' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get all the groups we're looking for +$allGroups = Get-DistributionGroup | Where-Object {$_.PrimarySmtpAddress -like $searchWildcard} + +# Initialise the hash table to store results in +$groupDetails = @() + +# Run through the groups getting the members and adding +foreach ($group in $allGroups) { + $groupMembers = (Get-DistributionGroupMember -Identity $group.Name).Alias -join '; ' + $groupDetails += [PSCustomObject]@{ + 'GroupName' = $group.Name; + 'GroupEmail' = $group.PrimarySmtpAddress; + 'GroupType' = $group.GroupType; + 'GroupMembers' = $groupMembers + } +} + +# Export results to CSV file +$groupDetails | Export-Csv -Path $outputFile -NoTypeInformation + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetMailboxPermissionsForList.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetMailboxPermissionsForList.ps1 new file mode 100644 index 0000000..a9f8a98 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetMailboxPermissionsForList.ps1 @@ -0,0 +1,40 @@ +# Get the permissions and sendas rights for a list of mailboxes and output them to CSV +# +# Uses the new PowerShell "module" that support MFA. +# + +# Where to save the CSV files to +$outputPath = 'C:\Temp\MailboxPermissions\' + +# What mailboxes are we checking? +$mailboxes = Get-Content -Path 'C:\Temp\Mailboxes.txt' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get all non-inherited mailbox permissions excluding self and output to a CSV file named for each mailbox +foreach ($mailbox in $mailboxes) { + Write-Output -InputObject ('Getting permissions for mailbox ' + $mailbox) + $mailboxPermissions = Get-MailboxPermission -Identity $mailbox | Where-Object {$_.IsInherited -eq $false -and $_.User -ne 'NT AUTHORITY\SELF'} | Select-Object Identity,User,AccessRights,Deny + if ($mailboxPermissions.Count -gt 0) { + $outputFile = $outputPath + 'MailboxPermissions_' + ($mailbox -replace '@','_') + '.csv' + $mailboxPermissions | Export-CSV -Path $outputFile -NoTypeInformation + } +} + +# Get all non-inherited recipient permissions (sendas) excluding self and output to a CSV file named for each mailbox +foreach ($mailbox in $mailboxes) { + Write-Output -InputObject ('Getting permissions for recipient ' + $mailbox) + $recipientPermissions = Get-RecipientPermission -Identity $mailbox | Where-Object {$_.IsInherited -eq $false -and $_.Trustee -ne 'NT AUTHORITY\SELF'} | Select-Object Identity,Trustee,AccessRights,AccessControlType + if ($recipientPermissions.Count -gt 0) { + $outputFile = $outputPath + 'RecipientPermissions_' + ($mailbox -replace '@','_') + '.csv' + $recipientPermissions | Export-CSV -Path $outputFile -NoTypeInformation + } +} + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetSharedMailboxPermissions.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetSharedMailboxPermissions.ps1 new file mode 100644 index 0000000..ac03562 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/GetSharedMailboxPermissions.ps1 @@ -0,0 +1,32 @@ +# Find shared mailboxes on the basis of their email domain and lists of who has access to them +# +# Uses the new PowerShell "module" that support MFA. +# + +# Where to save the CSV files to +$outputPath = 'C:\Temp\' + +# Wildcard for mailboxes to find +$searchWildcard = '*' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get all the mailboxes we're looking for +$sharedMailboxes = Get-Mailbox -RecipientTypeDetails SharedMailbox -ResultSize Unlimited | Where-Object {$_.PrimarySmtpAddress -like $searchWildcard} | Select-Object Name,Alias,PrimarySmtpAddress,ProhibitSendQuota + +# Export list of mailboxes to CSV File +$sharedMailboxes | Export-CSV -Path ($outputPath + 'Shared Mailboxes.csv') -NoTypeInformation + +# Get all non-inherited permissions excluding self and output to a CSV file named for each group +foreach ($sharedMailbox in $sharedMailboxes) { + $mailboxPermissions = Get-MailboxPermission -Identity $sharedMailbox.alias | Where-Object {$_.IsInherited -eq $false -and $_.User -ne 'NT AUTHORITY\SELF'} | Select-Object Identity,User,AccessRights,Deny + $mailboxPermissions | Export-CSV -Path ($outputPath + $sharedMailbox.Name + '.csv') -NoTypeInformation +} + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/README.md b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/README.md new file mode 100644 index 0000000..f14aef9 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/README.md @@ -0,0 +1,27 @@ +# Exchange Online with MFA Support + +## What is this? + +Connecting to Exchange Online through a remote PowerShell session doesn't work when using multi factor authentication. You can (apparrently) get round that by creating an application password, but I've never got it to work and in my mind creating a password to bypass MFA somewhat defeates the point of enabling MFA in the first place. + +There now is a new "module" available which does support MFA, so this folder is where I'll be putting new scripts that support MFA or old scripts as I update them. + +## Pre-requisites + +To connect using MFA you have to locally install a new module from Microsoft. Which for whatever reason isn't available from PSGallery, nor can it be simply downloaded. Instead it has to be installed from within the Exchange Online admin centre using one of those annoying ClickOnce installers that only work in MS's own web browsers. + +Microsoft have a document explaining the unnecessarily convulted install process here: + +[Connect to Exchange Online PowerShell using multi-factor authentication](https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/mfa-connect-to-exchange-online-powershell?view=exchange-ps) + +In addition, because this will be using a remote session it will require the script execution policy within PowerShell to be changed to RemoteSigned. This is done either globally with: + +`Set-ExecutionPolicy -ExecutionPolicy RemoteSigned` + +Or for the current user with: + +`Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser` + +## Disclaimer + +All scripts are provided as is without warranty of any kind, use them at your own risk. diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/ResetCalendarDefaultPermissions.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/ResetCalendarDefaultPermissions.ps1 new file mode 100644 index 0000000..579f458 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/ResetCalendarDefaultPermissions.ps1 @@ -0,0 +1,32 @@ +# Reset default calendar permissions to availability for a list of users. +# +# Uses the new PowerShell "module" that support MFA. +# + +# File with list of users +$userlistPath = 'C:\Temp\Userlist.txt' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get list of users +$userlist = Get-Content -Path $userlistPath + +# Get mailboxes for users in list +$mailboxes = Get-Mailbox -ResultSize Unlimited | Where-Object {$_.Name -in $userlist} | Sort-Object -Property Name + +# Check the mailboxes and reset any which have default permissions of None to AvailabilityOnly +foreach ($mailbox in $mailboxes) { + $calendarPath = $mailbox.UserPrincipalName + ':\Calendar' + $defaultPermissions = Get-MailboxFolderPermission -Identity $calendarPath -User 'Default' + if ($defaultPermissions.AccessRights -eq 'None') { + Set-MailboxFolderPermission -Identity $calendarPath -User 'Default' -AccessRights AvailabilityOnly + } +} + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/SetupForwardingForListOfUSers.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/SetupForwardingForListOfUSers.ps1 new file mode 100644 index 0000000..18b38a1 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/SetupForwardingForListOfUSers.ps1 @@ -0,0 +1,28 @@ +# A simple script to enable forwarding for a list of users from a CSV file +# +# The script is expecting the CSV file to have two columns called SourceAddress and DestinationAddress +# + +# Get the list of users from a CSV file +$userList = Import-Csv -Path 'C:\Temp\UserList.csv' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Get all non-inherited permissions excluding self and output to a CSV file named for each group +foreach ($user in $userList) { + Write-Output -InputObject ('Forwarding ' + $user.SourceAddress + ' to ' + $user.DestinationAddress) + Set-Mailbox -Identity $user.SourceAddress -ForwardingSmtpAddress $user.DestinationAddress +} + +# Pull back a list to check everything has worked correctly +foreach ($user in $userList) { + Get-Mailbox -Identity $user.SourceAddress | Select-Object UserPrincipalName,ForwardingSmtpAddress,DeliverToMailboxAndForward +} + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/SetupRoomMailbox.ps1 b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/SetupRoomMailbox.ps1 new file mode 100644 index 0000000..a8fc504 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/ExchangeWithMFA/SetupRoomMailbox.ps1 @@ -0,0 +1,52 @@ +# Create and set up a room mailbox. +# +# Uses the new PowerShell "module" that support MFA. +# + +# New room name and alias +$displayName = '' +$mailboxAlias = '' + +# How many people can the room take? +$roomCapacity = '' + +# Do you want meeting requests to be auto accepted? +$requestAutoAccept = $true + +# Do we want to add the room to a room list? +$addToRoomList = $true + +# What is the room list called? (Will be created if it doesn't exist) +$roomList = '' + +# Find and load the new ExO "module" +$exoModulePath = (Get-ChildItem -Path $env:userprofile -Filter CreateExoPSSession.ps1 -Recurse -Force -ErrorAction SilentlyContinue).DirectoryName[-1] +. "$exoModulePath\CreateExoPSSession.ps1" + +# Establish a session to Exchange Online +Connect-EXOPSSession + +# Create the new room mailbox +New-Mailbox -Room -Alias $mailboxAlias -Name $displayName -DisplayName $displayName -ResourceCapacity $roomCapacity + +# Wait for the meeting room mailbox to process +Start-Sleep -Seconds 30 + +# Set the mailbox calendar to auto accept meeting requests (assuming policies are met) +if ($requestAutoAccept) { + Set-CalendarProcessing $mailboxAlias -AutomateProcessing AutoAccept +} + +# If we're adding the room to a room list, then do that. +if ($addToRoomList) { + # If the room list doesn't exist, create it. + if (!(Get-DistributionGroup -Identity $roomList -ErrorAction SilentlyContinue)) { + New-DistributionGroup -Name $roomList -RoomList + } + + # Add the room to the list + Add-DistributionGroupMember -Identity $roomList -Member $mailboxAlias +} + +# End the Exchange Session +Get-PSSession | Where-Object {$_.ComputerName -eq 'outlook.office365.com'} | Remove-PSSession diff --git a/Powershell/PowerShell-Office365Admin/Intune/ScheduledBitlockerKeyBackup.ps1 b/Powershell/PowerShell-Office365Admin/Intune/ScheduledBitlockerKeyBackup.ps1 new file mode 100644 index 0000000..0462a1b --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/Intune/ScheduledBitlockerKeyBackup.ps1 @@ -0,0 +1,76 @@ +# ScheduledBitLockerKeyBackup.ps1 + +<# +Script intended for deployment through Intune: +Creates a locally saved PS script to get the bitlocker key and save it to Azure. +Then creates a scheduled task to run that script at every logon. +#> + +# Name and description for the schedulled task to be created +$taskName = 'Bitlocker Key Backup to AzureAD' +$taskDescription = 'Retrieve Bitlocker key for system drive and store it in AzureAD' + +# Day, time and randomised delay for the task to be created +$taskDay = 'Monday' +$taskTime = '12:00:00' +$taskDelay = '00:20:00' + +# Path to the folder for the files to be created +$scriptFolder = 'C:\ProgramData\Intune\Scripts\' + +# Names of the files to be created +$scriptFilename = 'BitlockerKeyBackup.ps1' +$scriptLogFilename = 'BitlockerKeyBackup-LastRun.log' +$deployLogFilename = 'BitlockerKeyBackup-Deployed.log' + +# Establish full paths to the files +$scriptPath = $scriptFolder + $scriptFilename +$logPath = $scriptFolder + $scriptLogFilename +$deployLogPath = $scriptFolder + $deployLogFilename + +# If folder doesn't exist create it, else clean up files from last run +if (!(Test-Path -Path $scriptFolder)) { + New-Item -Path $scriptFolder -ItemType Directory +} +else { + foreach ($filePath in @($scriptPath, $logPath, $deployLogPath)) { + if (Test-Path -Path $filePath) { + Remove-Item -Path $filePath + } + } +} + +# Contents of the PS script file to be created on the target machine +$scriptContents = @( + '$logPath = ''' + $logPath + '''' + 'try {' + ' $recoveryPassword = ((Get-BitlockerVolume -MountPoint $env:SystemDrive -ErrorAction Stop).KeyProtector | Where-Object {$_.KeyProtectorType -eq "RecoveryPassword"})' + ' $result = BackupToAAD-BitLockerKeyProtector $env:systemdrive -KeyProtectorId $recoveryPassword.KeyProtectorId -ErrorAction Stop' + ' Out-File -InputObject $result -FilePath $logPath' + '}' + 'catch {' + ' Out-File -InputObject $Error[0].Exception.Message -FilePath $logPath' + '}' +) + +# Create the script file +Out-File -InputObject $scriptContents -FilePath $scriptPath + +# Set up the various parts of the scheduled task +$taskArgument = '-ExecutionPolicy Bypass -Command ". ' + $scriptPath + '"' +$taskAction = New-ScheduledTaskAction -Execute 'powershell.exe' -Argument $taskArgument -WorkingDirectory $scriptFolder +$taskTrigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek $taskDay -At $taskTime -RandomDelay $taskDelay +$taskPrincipal = New-ScheduledTaskPrincipal -UserId 'SYSTEM' -LogonType 'ServiceAccount' -RunLevel 'Highest' +$taskSettings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -Compatibility 'Win8' -Hidden -StartWhenAvailable + +# If the scheduled task already exists then remove it +if (Get-ScheduledTask | Where-Object { $_.TaskName -eq $taskName }) { + Unregister-ScheduledTask -TaskName $taskName -Confirm:$false +} + +# Create the scheduled task and run it immediately +$taskCreated = Register-ScheduledTask -Action $taskAction -Trigger $taskTrigger -TaskName $taskName -Description $taskDescription -Principal $taskPrincipal -Settings $taskSettings +Start-ScheduledTask -TaskName $taskName + +# Create a log file for the deployment of the scheduled task +Out-File -InputObject $taskCreated -FilePath $deployLogPath diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/ADGUIDToImmutableID.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/ADGUIDToImmutableID.ps1 new file mode 100644 index 0000000..bdb845f --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/ADGUIDToImmutableID.ps1 @@ -0,0 +1,4 @@ +# Convert AD GUID to 365 ImmutableID + +$adGuid = Read-Host -Prompt 'Enter Active Directory GUID to convert to ImmutableID' +[System.Convert]::ToBase64String($adGuid.tobytearray()) diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkAddLicenceConditional.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkAddLicenceConditional.ps1 new file mode 100644 index 0000000..4846276 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkAddLicenceConditional.ps1 @@ -0,0 +1,22 @@ +# Bulk add a new licence to users on the basis of what licence they currently have +# +# This is useful for something like adding Office 365 ATP to everyone who currently has E3, for example. +# + +# What licence do the users currently have? +$existingLicence = '' + +# What licence are we adding? +$licenceToAdd = '' + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Find everyone who has the existing +$users = Get-MsolUser -All | Where-Object {($_.licenses).AccountSkuId -match $existingLicence -and !(($_.licenses).AccountSkuId -match $licenceToAdd)} + +# Add the new licence +foreach ($user in $users) { + Set-MSOLUserLicense -UserPrincipalName $user.UserPrincipalName –AddLicenses $licenceToAdd +} diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkAddLicences.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkAddLicences.ps1 new file mode 100644 index 0000000..6858979 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkAddLicences.ps1 @@ -0,0 +1,37 @@ +# Bulk add additional licences to a list of users where they already have a licence assigned. +# +# Only works where the user already has a licence assigned as assigning a licence to an unlicenced user is a different process. +# + +# Where is the list of user UPN's? +$userListPath = 'C:\Temp\UserList.txt' + +# What licences are we adding? +# List of available SKUs can be obtained with (Get-MsolAccountSku).AccountSkuId +$licencesToAdd = @('','') + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Import list of users from file +$users = Get-Content -Path $userListPath | Sort-Object + +# Add the new licence +foreach ($user in $users) { + $userDetails = Get-MSOLUser -UserPrincipalName $user + foreach ($licenceToAdd in $licencesToAdd) { + if ($userDetails.IsLicensed -eq $true) { + if (!(($userDetails.licenses).AccountSkuId -match $licenceToAdd)) { + Write-Output -InputObject ('Adding Licence ' + $licenceToAdd + ' to ' + $user + '.') + Set-MSOLUserLicense -UserPrincipalName $user –AddLicenses $licenceToAdd + } + else { + Write-Output -InputObject ('User ' + $user + ' already has ' + $licenceToAdd + ' licence assigned.') + } + } + else { + Write-Output -InputObject ('User ' + $user + ' has no existing licence assigned.') + } + } +} diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkChangeMFASetting.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkChangeMFASetting.ps1 new file mode 100644 index 0000000..5f7e29b --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkChangeMFASetting.ps1 @@ -0,0 +1,42 @@ +# Bulk enable or disable MFA for all users in a tenant +# + +# Enable or disable MFA? +$enableMFA = $true + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Enable or disable MFA +if ($enableMFA) { + # Create an object containing the authentication requirements + $authReq = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement + + # Include all relying parties + $authReq.RelyingParty = '*' + + # Set MFA state to enabled + # Enabled allows connected apps to keep working until the user completes MFA set up. + # This can also be set to enforced which would disconnect everything immediately. + $authReq.State = 'Enabled' + + # Set the cut off date before which registered devices should require re-connecting with MFA. + # Using the current date is recommended so that all previously connected devices have to be reconnected. + $authReq.RememberDevicesNotIssuedBefore = (Get-Date) + + # Find all licenced users who do not currently have MFA enabled or enforced + $usersToChange = Get-MsolUser | Where-Object {$_.StrongAuthenticationRequirements.State -notmatch 'Enabled|Enforced' -and $_.isLicensed -eq $true} + + # Enable MFA for those users + $usersToChange | Set-MsolUser -StrongAuthenticationRequirements $authReq +} +else { + # Find all licenced users who currently have MFA enabled or enforced + $usersToChange = Get-MsolUser | Where-Object {$_.StrongAuthenticationRequirements.State -match 'Enabled|Enforced' -and $_.isLicensed -eq $true} + + # Disable MFA for those users + $usersToChange | Set-MsolUser -StrongAuthenticationRequirements @() +} + + diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkChangeOnlineUserUPN.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkChangeOnlineUserUPN.ps1 new file mode 100644 index 0000000..7373b5e --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkChangeOnlineUserUPN.ps1 @@ -0,0 +1,22 @@ +# Bulk update Online User UPNs +# + +# What domain are we replacing? +$oldDomain = '' + +# What are we replacing it with? +$newDomain = '' + +# Import the MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Get all users using that domain as their UPN +$users = Get-MsolUser -All | Where-Object {$_.UserPrincipalName -match $oldDomain} + +# Run through the users replacing their UPN and keeping us updated on what's going on +foreach ($user in $users) { + $newUPN = $user.UserPrincipalName.Split('@')[0] + '@' + $newDomain + Write-Output -InputObject ('Setting UPN for user ' + $user.UserPrincipalName + ' to ' + $newUPN) + Set-MsolUserPrincipalName -UserPrincipalName $user.UserPrincipalName -NewUserPrincipalName $newUPN +} diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkDisableMFA.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkDisableMFA.ps1 new file mode 100644 index 0000000..3aa4592 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkDisableMFA.ps1 @@ -0,0 +1,12 @@ +# Disable MFA for all licenced users who currently have it enabled +# + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Find all licenced users who currently have MFA enabled or enforced +$usersToChange = Get-MsolUser | Where-Object {$_.StrongAuthenticationRequirements.State -match 'Enabled|Enforced' -and $_.isLicensed -eq $true} + +# Disable MFA for those users +$usersToChange | Set-MsolUser -StrongAuthenticationRequirements @() diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkEnableMFA.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkEnableMFA.ps1 new file mode 100644 index 0000000..33d50b0 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkEnableMFA.ps1 @@ -0,0 +1,26 @@ +# Enable MFA for all licenced users who don't currently have it enabled +# + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Create an object containing the authentication requirements +$authReq = New-Object -TypeName Microsoft.Online.Administration.StrongAuthenticationRequirement + +# Include all relying parties +$authReq.RelyingParty = '*' + +# Set MFA state to enabled +# Enabled allows connected apps to keep working until the user completes MFA set up. +# This can also be set to enforced which would disconnect everything immediately. +$authReq.State = 'Enabled' + +# Set the cut off date before which registered devices should require re-connecting with MFA +$authReq.RememberDevicesNotIssuedBefore = (Get-Date) + +# Find all licenced users who do not currently have MFA enabled or enforced +$usersToChange = Get-MsolUser | Where-Object {$_.StrongAuthenticationRequirements.State -notmatch 'Enabled|Enforced' -and $_.isLicensed -eq $true} + +# Enable MFA for those users +$usersToChange | Set-MsolUser -StrongAuthenticationRequirements $authReq diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkRemoveLicence.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkRemoveLicence.ps1 new file mode 100644 index 0000000..bb147d0 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkRemoveLicence.ps1 @@ -0,0 +1,17 @@ +# Bulk remove a licence from users +# + +# What licence are we removing? +$licenceToRemove = '' + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Find everyone who has the licence to be removed +$users = Get-MsolUser -All | Where-Object {($_.licenses).AccountSkuId -match $licenceToRemove} + +# Remove the licence +foreach ($user in $users) { + Set-MSOLUserLicense –user $user.UserPrincipalName –RemoveLicenses $licenceToRemove +} diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/BulkReplaceLicence.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/BulkReplaceLicence.ps1 new file mode 100644 index 0000000..bb2e9ba --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/BulkReplaceLicence.ps1 @@ -0,0 +1,21 @@ +# Bulk replace a licence for all users who have the one being replaced. +# + +# What licence are we removing? +$licenceToRemove = '' + +# What licence are we adding? +$licenceToAdd = '' + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Find everyone who has the licence being replaced +$users = Get-MsolUser -All | Where-Object {($_.licenses).AccountSkuId -match $licenceToRemove} + +# Remove the old licence and add the new one +foreach ($user in $users) { + Set-MSOLUserLicense –user $user.UserPrincipalName –RemoveLicenses $licenceToRemove + Set-MSOLUserLicense –user $user.UserPrincipalName -AddLicenses $licenceToAdd +} diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/ChangeOnlineUserUPN.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/ChangeOnlineUserUPN.ps1 new file mode 100644 index 0000000..3c5b05f --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/ChangeOnlineUserUPN.ps1 @@ -0,0 +1,16 @@ +# Update Online User UPN - when AD sync doesn't do it. + +# Import the MSOL module and connect +Import-Module MSOnline +Connect-MsolService + +# Whose UPN are we changing? +$oldUPN = Read-Host -Prompt 'Enter user''s old UPN in the format username@domain' + +# What are we changing it to? +$newUPN = Read-Host -Prompt 'Enter user''s new UPN in the format username@domain' + +# Change the UPN +if (Get-ADUser -Identity $newUPN.Split('@')[0]) { + Set-MsolUserPrincipalName -UserPrincipalName $oldUPN -NewUserPrincipalName $newUPN +} diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/CompletelyDeleteAUser.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/CompletelyDeleteAUser.ps1 new file mode 100644 index 0000000..4c05b09 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/CompletelyDeleteAUser.ps1 @@ -0,0 +1,9 @@ +# Delete a user and then delete the deleted user + +Import-Module MSOnline +Connect-MsolService + +$upnToDelete = Read-Host -Prompt 'Enter UPN of user to delete in the format username@domain' + +Remove-MsolUser -UserPrincipalName $upnToDelete +Remove-MsolUser -UserPrincipalName $upnToDelete -RemoveFromRecycleBin diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/FixDuplicateSyncObject.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/FixDuplicateSyncObject.ps1 new file mode 100644 index 0000000..e9f538c --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/FixDuplicateSyncObject.ps1 @@ -0,0 +1,33 @@ +# Remove a duplicate 365 account created by a faulty sync and reconnect +# the orphaned 365 user to the AD account. +# + +# Get correct and incorrect account details +$adUsername = Read-Host -Prompt 'Enter username for AD account' +$msolIncorrectUPN = Read-Host -Prompt 'Enter UPN for the duplicate object in MSOL' + +# Connect to MS Online +Import-Module MSOnline +Connect-MsolService + +# Get AD user account +$adObject = Get-ADUser -Identity $adUsername + +# Get correct UPN from AD account +$msolCorrectUPN = $adObject.UserPrincipalName + +# +try { + Get-MsolUser -UserPrincipalName $msolCorrectUPN -ErrorAction Stop + + Remove-MSOLuser -UserPrincipalName $msolIncorrectUPN + Remove-MSOLuser -UserPrincipalName $msolIncorrectUPN -RemoveFromRecycleBin + + $adGuid = $adObject.ObjectGuid + $immutableID = [System.Convert]::ToBase64String($adGuid.ToByteArray()) + + Set-MSOLuser -UserPrincipalName $msolCorrectUPN -ImmutableID $immutableID +} +catch { + Write-Host 'No account found in Azure AD matching the UPN for that AD account.' +} diff --git a/Powershell/PowerShell-Office365Admin/MSOnline/ImmutableIDToADGUID.ps1 b/Powershell/PowerShell-Office365Admin/MSOnline/ImmutableIDToADGUID.ps1 new file mode 100644 index 0000000..072c530 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/MSOnline/ImmutableIDToADGUID.ps1 @@ -0,0 +1,4 @@ +# Convert 365 ImmutableID to AD GUID + +$immutableID = Read-Host -Prompt 'Enter ImmutableID to convert to Active Directory GUID' +[GUID][System.Convert]::FromBase64String($immutableID) diff --git a/Powershell/PowerShell-Office365Admin/OneDrive/GetOneDriveQuotas.ps1 b/Powershell/PowerShell-Office365Admin/OneDrive/GetOneDriveQuotas.ps1 new file mode 100644 index 0000000..a997021 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/OneDrive/GetOneDriveQuotas.ps1 @@ -0,0 +1,18 @@ +# Retrive a list of all OneDrive for Business sites within the organisation +# +# Requires the Sharepoint Online PowerShell module to be installed +# + +# The name of your Office 365 organization +# This can be found in your Sharepoint URL before the '-my', eg: https://thecompany-my.sharepoint.com/ +$spoTenantName='' + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Create the common base URL for OneDrive for Business +$spoBaseWildcard = 'https://' + $spoTenantName + '-my.sharepoint.com/personal/*' + +# Get a list of all 'personal' sites (e.g.: OneDrive for Business sites) within the tenant +Get-SPOSite -Limit all -IncludePersonalSite $true | Where-Object {$_.Url -like $spoBaseWildcard} | Select-Object Owner,URL,StorageQuota | Format-Table -AutoSize diff --git a/Powershell/PowerShell-Office365Admin/OneDrive/IncreaseOneDriveQuota.ps1 b/Powershell/PowerShell-Office365Admin/OneDrive/IncreaseOneDriveQuota.ps1 new file mode 100644 index 0000000..2b39d62 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/OneDrive/IncreaseOneDriveQuota.ps1 @@ -0,0 +1,47 @@ +# Increase the size of specific users' OneDrive for Business accounts +# +# Requires the Sharepoint Online PowerShell module to be installed +# + +# The name of your Office 365 organization +# This can be found in your Sharepoint URL before the '-my', eg: https://thecompany-my.sharepoint.com/ +$spoTenantName='' + +# The size you want to increase to in TB. +$newSize = 1 + +# The list of UPNs for the accounts you wich to add the secondary admin to (list can contain a single item if required) +$userList = @('','') + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Create the base URL for OneDrive for Business +$spoBaseURL = 'https://' + $spoTenantName + '-my.sharepoint.com/personal/' + +# Convert new size to bytes +$newBytes = $newSize * 1048576 + +# Increase size for each user in list +foreach ($userUPN in $userList) { + $spoURL = $spoBaseURL + ($userUPN.ToLower() -replace "[@.]", "_") + try { + $currentBytes = (Get-SPOSite -Identity $spoURL -ErrorAction:Stop).StorageQuota + if ($currentBytes -gt $newBytes) { + try { + Set-SPOSite -Identity $spoURL -StorageQuota $newBytes -ErrorAction:Stop + Write-Output -InputObject ('Updated OneDrive account limit for ' + $userUPN + ' to ' + $newSize + 'TB.') + } + catch { + Write-Output -InputObject ('Failed to update OneDrive account limit for ' + $userUPN + '.') + } + } + else { + Write-Output -InputObject ('OneDrive account limit for ' + $userUPN + ' already equal to or higher than ' + $newSize + 'TB.') + } + } + catch { + Write-Output -InputObject ('No OneDrive account found for ' + $userUPN + '.') + } +} diff --git a/Powershell/PowerShell-Office365Admin/OneDrive/IncreaseOneDriveQuotaAll.ps1 b/Powershell/PowerShell-Office365Admin/OneDrive/IncreaseOneDriveQuotaAll.ps1 new file mode 100644 index 0000000..dc06379 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/OneDrive/IncreaseOneDriveQuotaAll.ps1 @@ -0,0 +1,44 @@ +# Increase the size of all users' OneDrive for Business accounts +# +# Requires the Sharepoint Online PowerShell module to be installed +# + +# The name of your Office 365 organization +# This can be found in your Sharepoint URL before the '-my', eg: https://thecompany-my.sharepoint.com/ +$spoTenantName='' + +# The size you want to increase to in TB. +$newSize = 1 + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Create the common base URL for OneDrive for Business +$spoBaseWildcard = 'https://' + $spoTenantName + '-my.sharepoint.com/personal/*' + +# Convert new size to bytes +$newBytes = $newSize * 1048576 + +# Get a list of all personal sites within the tenant. +$personalSites = Get-SPOSite -Limit all -IncludePersonalSite $true | Where-Object {$_.Url -like $spoBaseWildcard} + +# Increase size for each user in turn. +foreach ($personalSite in $personalSites) { + $spoURL = $personalSite.Url + $userUPN = $personalSite.Owner + $currentBytes = $personalSite.StorageQuota + + if ($currentBytes -lt $newBytes) { + try { + Set-SPOSite -Identity $spoURL -StorageQuota $newBytes -ErrorAction:Stop + Write-Output -InputObject ('Updated OneDrive account limit for ' + $userUPN + ' to ' + $newSize + 'TB.') + } + catch { + Write-Output -InputObject ('Failed to update OneDrive account limit for ' + $userUPN + '.') + } + } + else { + Write-Output -InputObject ('OneDrive account limit for ' + $userUPN + ' already equal to or higher than ' + $newSize + 'TB.') + } +} diff --git a/Powershell/PowerShell-Office365Admin/OneDrive/OneDriveForBusinessAddAdmin.ps1 b/Powershell/PowerShell-Office365Admin/OneDrive/OneDriveForBusinessAddAdmin.ps1 new file mode 100644 index 0000000..055a6e7 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/OneDrive/OneDriveForBusinessAddAdmin.ps1 @@ -0,0 +1,27 @@ +# Add a collection administrator to your users' OneDrive for Business accounts +# +# Requires the Sharepoint Online PowerShell module to be installed +# + +# The name of your Office 365 organization +# This can be found in your Sharepoint URL before the '-my', eg: https://thecompany-my.sharepoint.com/ +$spoTenantName='' + +# The UPN of the account you wish to add as a secondary admin +$secondaryAdminUPN = '' + +# The list of UPNs for the accounts you wich to add the secondary admin to +$userList = @('','') + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Create the base URL for OneDrive for Business +$spoBaseURL = 'https://' + $spoTenantName + '-my.sharepoint.com/personal/' + +# Add secondary admin to each user in the list +foreach ($userUPN in $userList) { + $spoURL = $spoBaseURL + ($userUPN.ToLower() -replace "[@.]", "_") + Set-SPOUser -Site $spoURL -LoginName $secondaryAdminUPN -IsSiteCollectionAdmin $true -ErrorAction:Continue +} diff --git a/Powershell/PowerShell-Office365Admin/OneDrive/OneDriveForBusinessRemoveAdmin.ps1 b/Powershell/PowerShell-Office365Admin/OneDrive/OneDriveForBusinessRemoveAdmin.ps1 new file mode 100644 index 0000000..450cf11 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/OneDrive/OneDriveForBusinessRemoveAdmin.ps1 @@ -0,0 +1,28 @@ +# Remove a collection administrator from your users' OneDrive for Business accounts +# +# Requires the Sharepoint Online PowerShell module to be installed +# + +# The name of your Office 365 organization +# This can be found in your Sharepoint URL before the '-my', eg: https://thecompany-my.sharepoint.com/ +$spoTenantName='' + +# The UPN of the account you wish to add as a secondary admin +$secondaryAdminUPN = '' + +# The list of UPNs for the accounts you wich to add the secondary admin to +$userList = @('','') + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Create the base URL for OneDrive for Business +$spoBaseURL = 'https://' + $spoTenantName + '-my.sharepoint.com/personal/' + +# Add secondary admin to each user in the list +foreach ($userUPN in $userList) { + $spoURL = $spoBaseURL + ($userUPN.ToLower() -replace "[@.]", "_") + Set-SPOUser -Site $spoURL -LoginName $secondaryAdminUPN -IsSiteCollectionAdmin $false -ErrorAction:Continue + Remove-SPOUser -Site $spoURL -LoginName $secondaryAdminUPN +} diff --git a/Powershell/PowerShell-Office365Admin/OneDrive/ResetOneDriveQuotas.ps1 b/Powershell/PowerShell-Office365Admin/OneDrive/ResetOneDriveQuotas.ps1 new file mode 100644 index 0000000..11b959c --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/OneDrive/ResetOneDriveQuotas.ps1 @@ -0,0 +1,27 @@ +# Retrive a list of all OneDrive for Business sites, check their size and reset it if it is less than the default +# +# Requires the Sharepoint Online PowerShell module to be installed +# + +# The name of your Office 365 organization +# This can be found in your Sharepoint URL before the '-my', eg: https://thecompany-my.sharepoint.com/ +$spoTenantName='' + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Create the common base URL for OneDrive for Business +$spoBaseWildcard = 'https://' + $spoTenantName + '-my.sharepoint.com/personal/*' + +# Get the default quota for the tenant +$defaultQuota = (Get-SPOTenant).OneDriveStorageQuota + +# Get a list of all 'personal' sites (e.g.: OneDrive for Business sites) within the tenant +$usersToReset = Get-SPOSite -Limit all -IncludePersonalSite $true | Where-Object {$_.Url -like $spoBaseWildcard -and $_.StorageQuota -lt $defaultQuota} + +# Get a list of all 'personal' sites (e.g.: OneDrive for Business sites) within the tenant +foreach ($userToReset in $usersToReset) { + Write-Output -InputObject ('Resetting user ' + $userToReset.Owner) + Set-SPOSite -Identity $userToReset.Url -StorageQuotaReset +} diff --git a/Powershell/PowerShell-Office365Admin/SharePoint/CheckAllSitesForUser.ps1 b/Powershell/PowerShell-Office365Admin/SharePoint/CheckAllSitesForUser.ps1 new file mode 100644 index 0000000..177181d --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SharePoint/CheckAllSitesForUser.ps1 @@ -0,0 +1,49 @@ +# Script to go through all SPO sites and check if a user is assigned to them +# + +# This is the name of your tenant, as shown in the URL when accessing SharePoint online +# E.g.: https://.sharepoint.com/ +$spoTenantName = '' + +# Who are we looking for? (uses a wildcard like comparison) +$loginNameLike = '' + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Get all SharePoint Online sites +$allSpoSites = Get-SPOSite -Limit All + +# Run through the sites... +foreach ($spoSite in $allSpoSites) { + # Try to get a list of users for the current site - requires owner access to the site. + try { + $spoUsers = Get-SPOUser -Site $spoSite.Url -Limit All -ErrorAction:Stop | Where-Object {$_.LoginName -like $loginNameLike} + $usersRetrived = $true + } + catch { + $spoUsers = '' + $usersRetrived = $false + } + + # If the previous try didn't fail then work on the retrived list + if ($usersRetrived) { + # If the list isn't empty, then set the output message to the userlogin name and site URL. + if ([string]$spoUsers.Count -gt 0) { + foreach ($spoUser in $spoUsers) { + $outputMessage = 'User ' + $spoUser.LoginName + ' found in site ' + $spoSite.Url + } + } + # Else (if the list is empty) set the output message to reflect that the user wasn't found in that group. + else { + $outputMessage = 'User not found in site ' + $spoSite.Url + } + } + # If users weren't retrived then set the output message to reflect that. + else { + $outputMessage = 'Unable to get users from site: ' + $spoSite.Url + } + # Finally write out the output message. + Write-Output -InputObject $outputMessage +} diff --git a/Powershell/PowerShell-Office365Admin/SharePoint/GetSiteDetails.ps1 b/Powershell/PowerShell-Office365Admin/SharePoint/GetSiteDetails.ps1 new file mode 100644 index 0000000..54bf210 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SharePoint/GetSiteDetails.ps1 @@ -0,0 +1,33 @@ +# Script to go through all SPO sites and check if a user is assigned to them +# + +# This is the name of your tenant, as shown in the URL when accessing SharePoint online +# E.g.: https://.sharepoint.com/ +$spoTenantName = '' + +# Who are we looking for? (uses a wildcard like comparison) +$siteNameLike = '*' + +# Connect to Sharepoint Online +Import-Module Microsoft.Online.SharePoint.PowerShell -DisableNameChecking +Connect-SPOService -Url ('https://' + $spoTenantName + '-admin.sharepoint.com') + +# Get all SharePoint Online sites +$allSpoSites = Get-SPOSite -Limit All | Where-Object {$_.Title -like $siteNameLike} + +Get-SpoSiteGroup + + +# Run through the sites... +foreach ($spoSite in $allSpoSites) { + # Try to get a list of users for the current site - requires owner access to the site. + $allSiteGroups = Get-SpoSiteGroup -Site $spoSite.Url + foreach ($siteGroup in $allSiteGroups) { + Write-Host + $siteGroup | Select-Object -ExpandProperty Users + } +} + +$spoUsers | Export-Csv C:\Temp\SISLive-Sharepoint-Site.csv -NoTypeInformation + +$allSpoSites \ No newline at end of file diff --git a/Powershell/PowerShell-Office365Admin/SkypeForBusiness/BulkEnableAudioConferencing.ps1 b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/BulkEnableAudioConferencing.ps1 new file mode 100644 index 0000000..7c0d499 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/BulkEnableAudioConferencing.ps1 @@ -0,0 +1,37 @@ +# Enable all licenced users for Microsoft audio conferencing +# +# In addition to the SfB module this requires the MSOnline module so it can check who is licenced. +# + +# Import MSOnline module and connect +Import-Module MSOnline +Connect-MsolService + +# Load the Skype Online Connector module and connect +Import-Module SkypeOnlineConnector +$sfbSession = New-CsOnlineSession +Import-PSSession -Session $sfbSession + +# This can be just one licence, or several, eg. MCOMEETADV (audio conferencing), ENTERPRISEPREMIUM (E5) and MEETING_ROOM all include audio conferencing. +# List of available SKUs can be obtained with (Get-MsolAccountSku).AccountSkuId +$audioConferencingLicences = @('MCOMEETADV','ENTERPRISEPREMIUM','MEETING_ROOM') + +# Find everyone who has the audio conferencing licence(s) assigned +$users = @() +foreach ($audioConferencingLicence in $audioConferencingLicences) { + $users += (Get-MsolUser -All | Where-Object {($_.licenses).AccountSkuId -match $audioConferencingLicence}).UserPrincipalName +} + +# Get the default service number from your tenant +$defaultServiceNumber = (Get-CsOnlineDialInConferencingBridge -Name 'Conference Bridge').DefaultServiceNumber + +# Enable conferencing for everyone on that list who doesn't already have it enabled +foreach ($user in $users) { + $currentProvider = (Get-CsOnlineDialInConferencingUserInfo -Identity $user).Provider + if ($currentProvider -ne 'Microsoft') { + Enable-CsOnlineDialInConferencingUser -ServiceNumber $defaultServiceNumber -ReplaceProvider -SendEmail + } +} + +# Disconnect +Remove-PSSession -Session $sfbSession diff --git a/Powershell/PowerShell-Office365Admin/SkypeForBusiness/EnableAudioConferencingForList.ps1 b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/EnableAudioConferencingForList.ps1 new file mode 100644 index 0000000..8b710f9 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/EnableAudioConferencingForList.ps1 @@ -0,0 +1,44 @@ +# Enable Microsoft audio conferencing for a list of users +# +# Expects a CSV file with two columns, one containing the UserPrincipalName and the other containing the ServiceNumber. +# +# A list of dedicated conference numbers can be retrieved with: +# (Get-CsOnlineDialInConferencingBridge -Name 'Conference Bridge').ServiceNumbers | Where-Object {$_.IsShared -eq $false} +# +# If the service number entry for a user in the CSV file is blank then the default will be used. +# + +# Where is the list of users? +$userListPath = 'C:\Temp\UserList.csv' + +# Load the Skype Online Connector module and connect +Import-Module SkypeOnlineConnector +$sfbSession = New-CsOnlineSession +Import-PSSession -Session $sfbSession + +# Get list of users from file +$users = Import-Csv -Path $userListPath + +# Get the conference bridge details +$conferenceBridge = Get-CsOnlineDialInConferencingBridge -Name 'Conference Bridge' + +# Enable conferencing for everyone on that list who doesn't already have it enabled +foreach ($user in $users) { + if (($user.ServiceNumber).Length -gt 0) { + $serviceNumber = $conferenceBridge.ServiceNumbers | Where-Object {$_.Number -eq $user.ServiceNumber} + } + else { + $serviceNumber = $conferenceBridge.DefaultServiceNumber + } + $currentProvider = (Get-CsOnlineDialInConferencingUserInfo -Identity $user.UserPrincipalName).Provider + if ($currentProvider -ne 'Microsoft') { + Enable-CsOnlineDialInConferencingUser -Identity $user.UserPrincipalName -ServiceNumber $serviceNumber.Number -ReplaceProvider -SendEmail + Write-Output -InputObject ('Audio conferencing enabled for ' + $user.UserPrincipalName + ' with number ' + $serviceNumber.Number + '.') + } + else { + Write-Output -InputObject ('Audio conferencing already enabled for ' + $user.UserPrincipalName + '.') + } +} + +# Disconnect +Remove-PSSession -Session $sfbSession diff --git a/Powershell/PowerShell-Office365Admin/SkypeForBusiness/EnableSkypeModernAuth.ps1 b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/EnableSkypeModernAuth.ps1 new file mode 100644 index 0000000..240973a --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/EnableSkypeModernAuth.ps1 @@ -0,0 +1,18 @@ +# Enable Modern Authentication in Skype for Business Online +# + +# Load the Skype Online Connector module +Import-Module SkypeOnlineConnector + +# Establish a session to Exchange Online +$sfbSession = New-CsOnlineSession +Import-PSSession -Session $sfbSession + +# Enable modern authentication +Set-CsOAuthConfiguration -ClientAdalAuthOverride Allowed + +# Verify the setting has changed +Get-CsOAuthConfiguration | Format-Table -AutoSize Identity,ClientAdalAuthOverride + +# End the PS Session +Remove-PSSession -Session $sfbSession diff --git a/Powershell/PowerShell-Office365Admin/SkypeForBusiness/ExportAll3rdPartyConferencing.ps1 b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/ExportAll3rdPartyConferencing.ps1 new file mode 100644 index 0000000..f65fd79 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/ExportAll3rdPartyConferencing.ps1 @@ -0,0 +1,74 @@ +# Script to extract conferencing details for users from the AcpInfo setting +# + +# Load the Skype Online Connector module +Import-Module SkypeOnlineConnector + +# Establish a session to Exchange Online +$sfbSession = New-CsOnlineSession +Import-PSSession -Session $sfbSession + +# Company Wildcard +$companyWildcard = '*' + +# AcpInfo Wildcard +$acpInfoWildcard = '*BT*' + +# Output file +$outputFile = 'C:\Temp\ConferencingUsers.csv' + +# Get all conferencing users matching the above wildcarded info +$conferencingUsers = Get-CsOnlineUser -WarningAction:SilentlyContinue -ErrorAction:SilentlyContinue | Where-Object {($_.Company -like $companyWildcard) -and ($_.AcpInfo -like $acpInfoWildcard) -and ($_.Enabled -eq $true)} | Select-Object DisplayName,UserPrincipalName,AcpInfo + +# Set up user details hash table +$userDetails = @() + +# Run through the users, check if they're in the exclusions list and if not then pull the details out of the AcpInfo code +foreach ($conferencingUser in $conferencingUsers) { + $tollNumber = '' + if ([string]$conferencingUser.AcpInfo -match '(?.*)') { + $tollNumber = $Matches.tollNumber + } + + $tollFreeNumber = '' + if ([string]$conferencingUser.AcpInfo -match '(?.*)') { + $tollFreeNumber = $Matches.tollFreeNumber + } + + $participantPassCode = '' + if ([string]$conferencingUser.AcpInfo -match '(?.*)') { + $participantPassCode = $Matches.participantPassCode + } + + $domain = '' + if ([string]$conferencingUser.AcpInfo -match '(?.*)') { + $domain = $Matches.domain + } + + $name = '' + if ([string]$conferencingUser.AcpInfo -match '(?.*)') { + $name = $Matches.name + } + + $url = '' + if ([string]$conferencingUser.AcpInfo -match '(?.*)') { + $url = $Matches.url + } + + $userDetails += [PSCustomObject]@{ + 'DisplayName' = [string]$conferencingUser.DisplayName + 'UserPrincipalName' = [string]$conferencingUser.UserPrincipalName + 'TollNumber' = [string]$tollNumber + 'TollFreeNumber' = [string]$tollFreeNumber + 'ParticipantPassCode' = [string]$participantPassCode + 'Domain' = [string]$domain + 'Name' = [string]$name + 'Url' = [string]$url + } +} + +# Output to CSV file +$userDetails | Export-Csv -Path $outputFile -NoTypeInformation + +# End the PS Session +Remove-PSSession -Session $sfbSession diff --git a/Powershell/PowerShell-Office365Admin/SkypeForBusiness/Remove3rdPartyConferencing.ps1 b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/Remove3rdPartyConferencing.ps1 new file mode 100644 index 0000000..9ac1237 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/Remove3rdPartyConferencing.ps1 @@ -0,0 +1,27 @@ +# Script to bulk remove 3rd party conferencing details for all users +# + +# Load the Skype Online Connector module +Import-Module SkypeOnlineConnector + +# Establish a session to Exchange Online +$sfbSession = New-CsOnlineSession +Import-PSSession -Session $sfbSession -AllowClobber + +# Company Wildcard +$companyWildcard = '*' + +# AcpInfo to match (doesn't need to be the full name) +$acpInfoWildcard = '*BT*' + +# Get all conferencing users matching the above info +$thirdPartyAcpUsers = Get-CsOnlineUser -WarningAction:SilentlyContinue -ErrorAction:SilentlyContinue | Where-Object {($_.Company -like $companyWildcard) -and ($_.AcpInfo -like $acpInfoWildcard) -and ($_.Enabled -eq $true)} + +# Run through the users and remove their ACP info +foreach ($thirdPartyAcpUser in $thirdPartyAcpUsers) { + $acpInfoName = ([xml]$thirdPartyAcpUser.AcpInfo).acpInformation.name + Remove-CsUserAcp -Identity $thirdPartyAcpUser.Identity -Name $acpInfoName +} + +# End the PS Session +Remove-PSSession -Session $sfbSession diff --git a/Powershell/PowerShell-Office365Admin/SkypeForBusiness/RemoveACPForUserList.ps1 b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/RemoveACPForUserList.ps1 new file mode 100644 index 0000000..4ce51cd --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/RemoveACPForUserList.ps1 @@ -0,0 +1,26 @@ +# Script to bulk remove conferencing details for a list of users +# + +# Where is the list of user UPN's? +$userListPath = 'C:\Temp\UserList.txt' + +# Load the Skype Online Connector module +Import-Module SkypeOnlineConnector + +# Establish a session to Exchange Online +$sfbSession = New-CsOnlineSession +Import-PSSession -Session $sfbSession -AllowClobber + +# Import list of users from file +$userList = Get-Content -Path $userListPath | Sort-Object + +# Get CS Online user identities for all the users in the list +$csOnlineUsers = (Get-CsOnlineUser -WarningAction SilentlyContinue | Where-Object {$_.UserPrincipalName -in $userList}).Identity + +# Run through the users and remove their ACP info +foreach ($csOnlineUser in $csOnlineUsers) { + Remove-CsUserAcp -Identity $csOnlineUser +} + +# End the PS Session +Remove-PSSession -Session $sfbSession diff --git a/Powershell/PowerShell-Office365Admin/SkypeForBusiness/UpdateAudioConferencingForList.ps1 b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/UpdateAudioConferencingForList.ps1 new file mode 100644 index 0000000..6f655e0 --- /dev/null +++ b/Powershell/PowerShell-Office365Admin/SkypeForBusiness/UpdateAudioConferencingForList.ps1 @@ -0,0 +1,41 @@ +# Update Microsoft audio conferencing for a list of users +# +# Expects a CSV file with two columns, one containing the UserPrincipalName and the other containing the ServiceNumber. +# +# A list of dedicated conference numbers can be retrieved with: +# (Get-CsOnlineDialInConferencingBridge -Name 'Conference Bridge').ServiceNumbers | Where-Object {$_.IsShared -eq $false} +# +# If the service number entry for a user in the CSV file is blank then the default will be used. +# + +# Where is the list of users? +$userListPath = 'C:\Temp\UsersToUpdate.csv' + +# Load the Skype Online Connector module and connect +Import-Module SkypeOnlineConnector +$sfbSession = New-CsOnlineSession +Import-PSSession -Session $sfbSession + +# Get list of users from file +$users = Import-Csv -Path $userListPath + +# Get the conference bridge details +$conferenceBridge = Get-CsOnlineDialInConferencingBridge -Name 'Conference Bridge' + +# Enable conferencing for everyone on that list who doesn't already have it enabled +foreach ($user in $users) { + if (($user.ServiceNumber).Length -gt 0) { + $serviceNumber = $conferenceBridge.ServiceNumbers | Where-Object {$_.Number -eq $user.ServiceNumber} + } + else { + $serviceNumber = $conferenceBridge.DefaultServiceNumber + } + $currentTollNumber = (Get-CsOnlineDialInConferencingUserInfo -Identity $user.UserPrincipalName).DefaultTollNumber + if ($currentTollNumber -ne $user.ServiceNumber) { + Set-CsOnlineDialInConferencingUser -Identity $user.UserPrincipalName -ServiceNumber $serviceNumber.Number -SendEmail + Write-Output -InputObject ('Audio conferencing updated for ' + $user.UserPrincipalName + ' with number ' + $serviceNumber.Number + '.') + } +} + +# Disconnect +Remove-PSSession -Session $sfbSession diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Convert-ADDistinguishedNameForAllUser.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Convert-ADDistinguishedNameForAllUser.ps1 new file mode 100644 index 0000000..37c961c --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Convert-ADDistinguishedNameForAllUser.ps1 @@ -0,0 +1,130 @@ +<# + .SYNOPSIS + Update the DistinguishedName Attribute for all Active Directory Users + + .DESCRIPTION + Update the DistinguishedName Attribute for all Active Directory Users. + It will update the 'CN=' to match the SamAccountName + + .EXAMPLE + PS C:\> .\Convert-ADDistinguishedNameForAllUser.ps1 + + .NOTES + MIND THE GAP: + This will change the DistinguishedName and this might break things + + It will only update/change the DistinguishedName if the 'CN=' does NOT match the SamAccountName + + I created this to bulk migrate older users, they had german umlauts and other crappy character in the DistinguishedName + + .LINK + https://github.com/jhochwald/PowerShell-collection/ + + .LINK + Get-ADUser + + .LINK + Rename-ADObject +#> +[CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] +param () + +if ($pscmdlet.ShouldProcess('All Users', 'Set')) +{ + try + { + $AllUsers = (Get-ADUser -Filter * -Properties SamAccountName, UserPrincipalName, DistinguishedName -ErrorAction Stop | Select-Object -Property SamAccountName, UserPrincipalName, DistinguishedName | Where-Object -FilterScript { + ($_.UserPrincipalName) -and ($_.SamAccountName) + }) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Stop + + break + } + + try + { + foreach ($User in $AllUsers) + { + $OldRDN = (($User | Select-Object -Property @{ + l = 'OldRDN' + e = { + $_.DistinguishedName.split(',')[0].split('=')[1] + } + }) | Select-Object -ExpandProperty OldRDN) + + if ($OldRDN -ne ($User.SamAccountName)) + { + # Mind the Gap: This will change the DistinguishedName and this might break things + $null = (Rename-ADObject -Identity $User.DistinguishedName -NewName $User.SamAccountName -Confirm:$false -ErrorAction Stop) + } + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADGroupUserMembership.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADGroupUserMembership.ps1 new file mode 100644 index 0000000..36c2c5e --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADGroupUserMembership.ps1 @@ -0,0 +1,399 @@ +function Copy-ADGroupUserMembership +{ + <# + .SYNOPSIS + Copy the membership of a given group to another group in Active Directory + + .DESCRIPTION + Copy the membership of a given group to another group in Active Directory. + By default only the members of the Source Group will be copied to the Target Group. + If the Parameter FULL is used, the members of the Target Group that are not a member of the Source Group will be removed. + If the Parameter SYNC is used, the Membership is synced between both groups. If a User is Member of the Target Group only, this membership will be copied to the Source as well. + + .PARAMETER SourceGroup + Source-Group Object. + + Specifies an Active Directory group object by providing one of the following values. The identifier in + parentheses is the LDAP display name for the attribute. + + Distinguished Name + + Example: CN=saradavisreports,OU=europe,CN=users,DC=corp,DC=contoso,DC=com + + GUID (objectGUID) + + Example: 599c3d2e-f72d-4d20-8a88-030d99495f20 + + Security Identifier (objectSid) + + Example: S-1-5-21-3165297888-301567370-576410423-1103 + + Security Accounts Manager (SAM) Account Name (sAMAccountName) + + Example: saradavisreports + + The cmdlet searches the default naming context or partition to find the object. If two or more objects are + found, the cmdlet returns a non-terminating error. + + This parameter can also get this object through the pipeline or you can set this parameter to an object + instance. + + .PARAMETER TargetGroup + Target-Group Object. + + Specifies an Active Directory group object by providing one of the following values. The identifier in + parentheses is the LDAP display name for the attribute. + + Distinguished Name + + Example: CN=saradavisreports,OU=europe,CN=users,DC=corp,DC=contoso,DC=com + + GUID (objectGUID) + + Example: 599c3d2e-f72d-4d20-8a88-030d99495f20 + + Security Identifier (objectSid) + + Example: S-1-5-21-3165297888-301567370-576410423-1103 + + Security Accounts Manager (SAM) Account Name (sAMAccountName) + + Example: saradavisreports + + The cmdlet searches the default naming context or partition to find the object. If two or more objects are + found, the cmdlet returns a non-terminating error. + + This parameter can also get this object through the pipeline or you can set this parameter to an object + instance. + + .PARAMETER full + Remove all memberships from the Targewt that does NOT exist in the the Source. + + .PARAMETER sync + Synchronies the group membership between Source-Group and Target-Group. + Even if a user is a member of the Target-Group only, it will be copied to the Source-Group as well. + + .EXAMPLE + PS C:\> Copy-ADGroupUserMembership -SourceGroup 'Sales' -TargetGroup 'Salesforce' + + Copy the membership of the Group 'Sales' to 'Salesforce' + + .EXAMPLE + PS C:\> Copy-ADGroupUserMembership -SourceGroup 'Sales' -TargetGroup 'Salesforce' -sync + + Copy the membership of the Group 'Sales' to 'Salesforce' and the other way around. + All Memberships of 'Salesforce' that does NOT exist in 'Sales' will be created in 'Sales' as well. + + .EXAMPLE + PS C:\> Copy-ADGroupUserMembership -SourceGroup 'Sales' -TargetGroup 'Salesforce' -full + + Copy the membership of the Group 'Sales' to 'Salesforce'. + All Memberships of 'Salesforce' that does NOT exist in 'Sales' will be removed. + + .NOTES + Initial AIT version of the function + + .LINK + https://github.com/jhochwald/PowerShell-collection/ + + .LINK + Get-ADGroupMember + + .LINK + Remove-ADGroupMember + + .LINK + Add-ADGroupMember + + .LINK + Copy-ADUserGroupMemberships + #> + [CmdletBinding(DefaultParameterSetName = 'default', + ConfirmImpact = 'Low', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Source-Group Object.')] + [ValidateNotNullOrEmpty()] + [Alias('Source')] + [string] + $SourceGroup, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Target-Group Object.')] + [ValidateNotNullOrEmpty()] + [Alias('Target')] + [string] + $TargetGroup, + [Parameter(ParameterSetName = 'full', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('RemoveTargetOnlyMembers')] + [switch] + $full = $null, + [Parameter(ParameterSetName = 'sync', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('MakeFullSync')] + [switch] + $sync = $null + ) + + begin + { + if ($pscmdlet.ShouldProcess('Groups', 'Get information from Active Directory')) + { + try + { + $SourceMembers = (Get-ADGroupMember -Identity $SourceGroup -ErrorAction Stop | Select-Object -ExpandProperty distinguishedName | Sort-Object) + $TargetMembers = (Get-ADGroupMember -Identity $TargetGroup -ErrorAction Stop | Select-Object -ExpandProperty distinguishedName | Sort-Object) + + # Check if we have any diferences + if (($SourceMembers) -and ($TargetMembers)) + { + # Yep, there are differences + $Differences = (Compare-Object -ReferenceObject $SourceMembers -DifferenceObject $TargetMembers) + } + elseif (($SourceMembers) -and (-not($TargetMembers))) + { + # Target has no members + $Differences = 'SourceOnly' + } + elseif (-not($SourceMembers)) + { + # Source has no members + Write-Error -Message ('{0} has no members!' -f $SourceGroup) -ErrorAction Stop + } + else + { + # Nope, there are no differences + $Differences = $null + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Stop + + break + } + } + } + + process + { + + switch ($pscmdlet.ParameterSetName) + { + 'full' + { + if ($pscmdlet.ShouldProcess($TargetGroup, 'Set')) + { + if ($Differences) + { + Write-Verbose -Message 'Remove Target-User from all groups where the Source-User is not a member of.' + + $TargetOnlyMembers = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>') + + if ($TargetOnlyMembers) + { + try + { + foreach ($TargetOnlyMember in $TargetOnlyMembers.InputObject) + { + Write-Verbose -Message ('Process: {0}' -f $TargetOnlyMember) + + $paramRemoveADGroupMember = @{ + Identity = $TargetGroup + Members = $TargetOnlyMember + ErrorAction = 'Stop' + Confirm = $false + } + $null = (Remove-ADGroupMember @paramRemoveADGroupMember -Verbose) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue + } + } + else + { + Write-Verbose -Message 'No group difference found where the Target-User is a member and Source-User is not.' + } + } + } + } + 'sync' + { + if ($pscmdlet.ShouldProcess($SourceGroup, 'Set')) + { + if ($Differences) + { + Write-Verbose -Message 'Make the Source-user a Member of all Groups only the Target-User is a member of.' + + $TargetOnlyMembers = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>') + + if ($TargetOnlyMembers) + { + Write-Verbose -Message ('Process: {0}' -f $TargetOnlyMembers) + + try + { + $paramAddADGroupMember = @{ + Identity = $SourceGroup + Members = $TargetOnlyMembers.InputObject + ErrorAction = 'Stop' + Confirm = $false + } + $null = (Add-ADGroupMember @paramAddADGroupMember) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue + } + } + else + { + Write-Verbose -Message 'No group difference found where the Target-User is a member and Source-User is not.' + } + } + } + } + 'default' + { + # Do nothing special + } + } + + if ($pscmdlet.ShouldProcess($TargetGroup, 'Set')) + { + if ($Differences) + { + try + { + Write-Verbose -Message 'Process all Source-Group only members.' + + $paramAddADGroupMember = @{ + Identity = $TargetGroup + ErrorAction = 'Stop' + Confirm = $false + } + + if ($Differences -eq 'SourceOnly') + { + # Target has no members + $paramAddADGroupMember.Members = $SourceMembers + } + else + { + $paramAddADGroupMember.Members = ($Differences | Where-Object -Property SideIndicator -EQ -Value '<=' | Select-Object -ExpandProperty InputObject) + } + + $null = (Add-ADGroupMember @paramAddADGroupMember) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue + } + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADUserGroupMembership.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADUserGroupMembership.ps1 new file mode 100644 index 0000000..d2049f6 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADUserGroupMembership.ps1 @@ -0,0 +1,385 @@ +function Copy-ADUserGroupMembership +{ + <# + .SYNOPSIS + Copy group memberships from a given Source-User to a Target-User in Active Directory + + .DESCRIPTION + Copy group memberships from a given Source-User to a Target-User in Active Directory. + The function can also remove the Target-User from all groups where the Source-User is not a member off (optional) or make the Source-User a member of all groups where only the Target-User is a member of. + + .PARAMETER SourceUser + Source-User Object. + + Specifies an Active Directory user object by providing one of the following property values. + The identifier in parentheses is the LDAP display name for the attribute. + + Distinguished Name + + Example: CN=SaraDavis,CN=Europe,CN=Users,DC=corp,DC=contoso,DC=com + + GUID (objectGUID) + + Example: 599c3d2e-f72d-4d20-8a88-030d99495f20 + + Security Identifier (objectSid) + + Example: S-1-5-21-3165297888-301567370-576410423-1103 + + SAM account name (sAMAccountName) + + Example: saradavis + + .PARAMETER TargetUser + Target-User Object. + + Specifies an Active Directory user object by providing one of the following property values. + The identifier in parentheses is the LDAP display name for the attribute. + + Distinguished Name + + Example: CN=SaraDavis,CN=Europe,CN=Users,DC=corp,DC=contoso,DC=com + + GUID (objectGUID) + + Example: 599c3d2e-f72d-4d20-8a88-030d99495f20 + + Security Identifier (objectSid) + + Example: S-1-5-21-3165297888-301567370-576410423-1103 + + SAM account name (sAMAccountName) + + Example: saradavis + + .PARAMETER full + Remove the Target User from all groups where the Source-User is not a member of. + + .PARAMETER sync + Make the Source-User a member of all Groups where only the Target-User is a member of. + + .EXAMPLE + PS C:\> Copy-ADUserGroupMembership -SourceUser 'johndoe' -TargetUser 'janedoe' + + Make janedoe a member of all groups where johndoe is a member of. Existing group memberships of janedoe will NOT be removed. + + .EXAMPLE + PS C:\> Copy-ADUserGroupMembership -SourceUser 'johndoe' -TargetUser 'janedoe' -full + + Make janedoe a member of all groups where johndoe is a member of. Existing group memberships of janedoe WILL be removed. + + .EXAMPLE + PS C:\> Copy-ADUserGroupMembership -SourceUser 'johndoe' -TargetUser 'janedoe' -sync + + Make janedoe a member of all groups where johndoe is a member of. Existing group memberships of janedoe WILL be applied to johndoe. + Lets call this a reverse Full Sync :) + + .NOTES + Initial AIT version of the function + + .LINK + https://github.com/jhochwald/PowerShell-collection/ + + .LINK + Get-ADUser + + .LINK + Remove-ADGroupMember + + .LINK + Add-ADGroupMember + + .LINK + Copy-ADGroupUserMemberships + #> + [CmdletBinding(DefaultParameterSetName = 'default', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Source-User Object.')] + [ValidateNotNullOrEmpty()] + [Alias('Source')] + [string] + $SourceUser, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Target-User Object.')] + [ValidateNotNullOrEmpty()] + [Alias('Target')] + [string] + $TargetUser, + [Parameter(ParameterSetName = 'full', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('RemoveTargetOnlyGroups')] + [switch] + $full = $null, + [Parameter(ParameterSetName = 'sync', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('MakeFullSync')] + [switch] + $sync = $null + ) + + begin + { + if ($pscmdlet.ShouldProcess('User', 'Get information from Active Directory')) + { + try + { + # Get the Target-User + $TargetUserObject = (Get-ADUser -Identity $TargetUser -Properties memberOf -ErrorAction Stop) + + # Get the Source-User + $SourceUserObject = (Get-ADUser -Identity $SourceUser -Properties memberOf -ErrorAction Stop) + + # Sort and save the information we collected above + $SourceUserMembership = ($SourceUserObject.MemberOf | Sort-Object) + $TargetUserMembership = ($TargetUserObject.MemberOf | Sort-Object) + + # Check if we have any diferences + if (($SourceUserMembership) -and ($TargetUserMembership)) + { + # Yep, there are differences + $Differences = (Compare-Object -ReferenceObject $SourceUserMembership -DifferenceObject $TargetUserMembership) + } + else + { + # Nope, there are no differences + $Differences = $null + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Stop + + break + } + } + } + + process + { + switch ($pscmdlet.ParameterSetName) + { + 'full' + { + if ($pscmdlet.ShouldProcess($SourceUser, 'Set')) + { + if ($Differences) + { + Write-Verbose -Message 'Remove Target-User from all groups where the Source-User is not a member of.' + + $TargetOnlyGroups = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>') + + if ($TargetOnlyGroups) + { + foreach ($TargetOnlyGroup in $TargetOnlyGroups.InputObject) + { + Write-Verbose -Message ('Process: {0}' -f $TargetOnlyGroup) + + try + { + $paramRemoveADGroupMember = @{ + Identity = $TargetOnlyGroup + Members = $TargetUser + ErrorAction = 'Stop' + Confirm = $false + } + $null = (Remove-ADGroupMember @paramRemoveADGroupMember) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue + } + } + } + else + { + Write-Verbose -Message 'No group difference fround where the Target-User is a member and Source-User is not.' + } + } + } + } + 'sync' + { + if ($pscmdlet.ShouldProcess($SourceUser, 'Set')) + { + if ($Differences) + { + Write-Verbose -Message 'Make the Source-user a Member of all Groups only the Target-User is a member of.' + + $TargetOnlyGroups = ($Differences | Where-Object -Property SideIndicator -EQ -Value '=>') + + if ($TargetOnlyGroups) + { + foreach ($TargetOnlyGroup in $TargetOnlyGroups.InputObject) + { + Write-Verbose -Message ('Process: {0}' -f $TargetOnlyGroup) + + try + { + $paramAddADGroupMember = @{ + Identity = $TargetOnlyGroup + Members = $SourceUser + ErrorAction = 'Stop' + Confirm = $false + } + $null = (Add-ADGroupMember @paramAddADGroupMember) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue + } + } + } + else + { + Write-Verbose -Message 'No group difference fround where the Target-User is a member and Source-User is not.' + } + } + } + } + 'default' + { + # Do nothing special + } + } + + if ($pscmdlet.ShouldProcess($TargetUser, 'Set')) + { + if ($Differences) + { + $SourceOnlyGroups = ($Differences | Where-Object -Property SideIndicator -EQ -Value '<=') + + if ($SourceOnlyGroups) + { + Write-Verbose -Message 'Process all Groups where only the Source-user is a member of.' + + foreach ($SourceOnlyGroup in $SourceOnlyGroups.InputObject) + { + Write-Verbose -Message ('Process: {0}' -f $SourceOnlyGroup) + + try + { + $paramAddADGroupMember = @{ + Identity = $SourceOnlyGroup + Members = $TargetUser + ErrorAction = 'Stop' + Confirm = $false + } + $null = (Add-ADGroupMember @paramAddADGroupMember) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -ErrorAction Continue -WarningAction Continue + } + } + } + } + else + { + Write-Warning -Message 'No group difference fround where the Source-User is a member and Source-User is not.' -WarningAction Continue + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADUserGroupMembershipSimple.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADUserGroupMembershipSimple.ps1 new file mode 100644 index 0000000..30ea2a7 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Copy-ADUserGroupMembershipSimple.ps1 @@ -0,0 +1,224 @@ +function Copy-ADUserGroupMembershipSimple +{ + <# + .SYNOPSIS + Copy group memberships from a given Source User to a Target User(s) in Active Directory + + .DESCRIPTION + Copy group memberships from a given Source User to a Target User(s) in Active Directory. + Simple Version of Copy-ADUserGroupMemberships + + .PARAMETER SourceUser + Source-User Object. + + Specifies an Active Directory group object by providing one of the following values. + The identifier in parentheses is the LDAP display name for the attribute. + + Distinguished Name + Example: CN=johndoe,OU=europe,CN=users,DC=corp,DC=contoso,DC=com + + GUID (objectGUID) + Example: 599c3d2e-f72d-4d20-8a88-030d99495f20 + + Security Identifier (objectSid) + Example: S-1-5-21-3165297888-301567370-576410423-1103 + + Security Accounts Manager (SAM) Account Name (sAMAccountName) + Example: johndoe + + .PARAMETER TargetUser + Target-User Object. + + Specifies an Active Directory group object by providing one of the following values. + The identifier in parentheses is the LDAP display name for the attribute. + + Distinguished Name + Example: CN=janedoe,OU=europe,CN=users,DC=corp,DC=contoso,DC=com + + GUID (objectGUID) + Example: 599c3d2e-f72d-4d20-8a88-030d99495f20 + + Security Identifier (objectSid) + Example: S-1-5-21-3165297888-301567370-576410423-1103 + + Security Accounts Manager (SAM) Account Name (sAMAccountName) + Example: janedoe + + .PARAMETER PassThru + Use the -PassThru parameter with the previous command to receive feedback about what groups the Target is being added as a member of. + + .EXAMPLE + PS C:\> Copy-ADUserGroupMembershipSimple -SourceUser 'SourceUser' -TargetUser 'TargetUser' + + Copy group memberships from SourceUser to TargetUser + + .EXAMPLE + PS C:\> Copy-ADUserGroupMembershipSimple -SourceUser 'SourceUser' -TargetUser 'TargetUser1', 'TargetUser2' + + Copy group memberships from SourceUser to TargetUser1 and TargetUser2 + + .EXAMPLE + PS C:\> Copy-ADUserGroupMembershipSimple -SourceUser 'SourceUser' -TargetUser 'TargetUser' -PassThru + + Use the -PassThru parameter with the previous command to receive feedback about what groups the Target is being added as a member of. + + .NOTES + Releasenotes: + 1.0.0 2019-07-09: Initial Release + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + .LINK + Copy-ADUserGroupMemberships + + .LINK + https://github.com/jhochwald/PowerShell-collection/ + + .LINK + Get-ADUser + + .LINK + Add-ADGroupMember + #> + + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess = $true)] + param + ( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 0, + HelpMessage = 'Source-User Object.')] + [ValidateNotNullOrEmpty()] + [Alias('Source')] + [string] + $SourceUser, + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 1, + HelpMessage = 'Target-User Object.')] + [ValidateNotNullOrEmpty()] + [Alias('Target')] + [string[]] + $TargetUser, + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 2)] + [switch] + $PassThru = $null + ) + + process + { + if ($pscmdlet.ShouldProcess($TargetUser, 'Modify/add Group Membership')) + { + try + { + $paramGetADUser = @{ + Identity = $SourceUser + Properties = 'memberof' + Verbose = $(if ($pscmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent) + { + $true + } + else + { + $false + } + ) + } + + $paramAddADGroupMember = @{ + Members = $TargetUser + Verbose = $(if ($pscmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent) + { + $true + } + else + { + # Workaround: If not present it is empty not false + $false + } + ) + PassThru = $(if ($pscmdlet.MyInvocation.BoundParameters['PassThru'].IsPresent) + { + $true + } + else + { + # Workaround: If not present it is empty not false + $false + } + ) + } + + if (($pscmdlet.MyInvocation.BoundParameters['PassThru'].IsPresent)) + { + # Show the output / PassThru in a nice format + ((Get-ADUser @paramGetADUser) | Select-Object -ExpandProperty memberof | Add-ADGroupMember @paramAddADGroupMember | Select-Object -ExpandProperty SamAccountName) + } + else + { + # Do not show any output / Verbose will be shown + $null = ((Get-ADUser @paramGetADUser) | Select-Object -ExpandProperty memberof | Add-ADGroupMember @paramAddADGroupMember) + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Find-enADDuplicateServicePrincipalName.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Find-enADDuplicateServicePrincipalName.ps1 new file mode 100644 index 0000000..2e4ff39 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Find-enADDuplicateServicePrincipalName.ps1 @@ -0,0 +1,169 @@ +function Find-enADDuplicateServicePrincipalName +{ + <# + .SYNOPSIS + Find all duplicate Service Principal Names (SPNs) + + .DESCRIPTION + Find all duplicate Service Principal Names (SPNs) in the Active Directory + + .INPUTS + NONE + + .OUTPUTS + Boolean + + .EXAMPLE + PS C:\> Find-enADDuplicateServicePrincipalName + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + Active Directory PowerShell Module + + .LINK + https://www.enatec.io + + .LINK + Get-ADObject + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([bool])] + param () + + begin + { + # Create a new Object + $AllObject = @() + } + + process + { + try + { + # We use Get-ADObject because this seems to be fast enough + $paramGetADObject = @{ + Filter = "(objectClass -eq 'user') -or (objectClass -eq 'computer') -and (servicePrincipalName -like '*')" + Properties = 'SamAccountName', 'servicePrincipalName' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $AllServicePrincipalNames = (Get-ADObject @paramGetADObject) + + # Loop over the List we got from Get-ADObject + foreach ($SPNObject in $AllServicePrincipalNames) + { + $SamAccountName = $SPNObject.SamAccountName + $ServicePrincipalNames = $SPNObject.ServicePrincipalName + + + foreach ($ServicePrincipalName in $ServicePrincipalNames) + { + if ($AllObject.ServicePrincipalName -like $ServicePrincipalName) + { + $MatchedSPNs = ($AllObject.ServicePrincipalName -like $ServicePrincipalName) + + # Loop over the matching list og SPNs + foreach ($MatchSPN in $MatchedSPNs) + { + $MatchSamAccountName = $MatchSPN.SamAccountName + + # Ding. ding, we have a winner + if ($MatchSamAccountName -ne $SamAccountName) + { + $paramWriteWarning = @{ + Message = ('Duplicated SPN has been found for {0}!!!' -f $ServicePrincipalName) + ErrorAction = 'Continue' + WarningAction = 'Continue' + } + Write-Warning @paramWriteWarning + } + } + } + else + { + # Create a new Object + $SingleObject = (New-Object -TypeName PSObject -Property @{ + SamAccountName = $SamAccountName + ServicePrincipalName = $ServicePrincipalName + }) + + # Add the Values to the List + $AllObject += $SingleObject + + # Cleanup + $SingleObject = $null + } + } + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + # Dump all SPNs, if verbose + $AllObject | Out-String | Write-Verbose + + # Cleanup + $AllObject = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-ADUserLockout.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-ADUserLockout.ps1 new file mode 100644 index 0000000..29b7af4 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-ADUserLockout.ps1 @@ -0,0 +1,203 @@ +function Get-ADUserLockouts +{ + <# + .SYNOPSIS + Tracking down account lockout sources with PowerShell + + .DESCRIPTION + Tracking down account lockout sources with PowerShell + + .PARAMETER Identity + Just scan for a single User? + + .PARAMETER StartTime + Start-point + + .PARAMETER EndTime + Endpoint + + .EXAMPLE + PS C:\> Get-ADUserLockout + + Tracking down account lockout sources for all users for the last 7 days + + .EXAMPLE + Get-ADUser -Filter {Department -eq 'Development'} | Get-ADUserLockout + + Tracking down account lockout sources for all users in the Development Department for the last 7 days + + .EXAMPLE + Get-ADUserLockout -StartTime (Get-Date).AddDays(-2) -EndTime (Get-Date).AddDays(-1) + + Tracking down account lockout sources for all users for the last day + + .NOTES + Original by Anthony Howell (@ThePoShWolf) - MIT Licenses + Copyright (c) 2018 Anthony Howell + + .LINK + https://theposhwolf.com/howtos/Get-ADUserLockouts/ + + .LINK + https://github.com/ThePoShWolf/Utilities/blob/master/ActiveDirectory/Get-ADUserLockouts.ps1 + #> + [CmdletBinding(DefaultParameterSetName = 'All', + ConfirmImpact = 'None')] + [OutputType([pscustomobject])] + param + ( + [Parameter(ParameterSetName = 'ByUser', + ValueFromPipeline)] + [string] + $Identity, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('Start')] + [datetime] + $StartTime = (Get-Date).AddDays(-8), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('End')] + [datetime] + $EndTime = (Get-Date).AddDays(-1) + ) + + begin + { + $filterHt = @{ + LogName = 'Security' + ID = 4740 + } + + if ($PSBoundParameters.ContainsKey('StartTime')) + { + $filterHt['StartTime'] = $StartTime + } + + if ($PSBoundParameters.ContainsKey('EndTime')) + { + $filterHt['EndTime'] = $EndTime + } + + try + { + $PDCEmulator = ((Get-ADDomain -ErrorAction Stop).PDCEmulator) + + Write-Verbose -Message ('Use {0} to find the lockout events' -f $PDCEmulator) + + # Query the event log just once instead of for each user if using the pipeline + $events = (Get-WinEvent -ComputerName $PDCEmulator -FilterHashtable $filterHt -ErrorAction Stop) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Stop -Exception $e.Exception -TargetObject $e.CategoryInfo.TargetName + + break + } + + Write-Verbose -Message 'Found the following events:' + Write-Verbose -Message $events + } + + process + { + if ($PSCmdlet.ParameterSetName -eq 'ByUser') + { + try + { + Write-Verbose -Message ('Querry AD Info for {0}' -f $Identity) + + $user = (Get-ADUser -Identity $Identity -ErrorAction Stop) + + Write-Verbose -Message ('Found the following AD Info for {0}:' -f $Identity) + Write-Verbose -Message $user + + # Filter the events + $output = $events | Where-Object -FilterScript { + $_.Properties[0].Value -eq $user.SamAccountName + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Stop -Exception $e.Exception -TargetObject $e.CategoryInfo.TargetName + + break + } + } + else + { + $output = $events + } + + foreach ($event in $output) + { + [pscustomobject]@{ + UserName = $event.Properties[0].Value + CallerComputer = $event.Properties[1].Value + TimeStamp = $event.TimeCreated + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADDNSServerInformation.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADDNSServerInformation.ps1 new file mode 100644 index 0000000..5fdc9b9 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADDNSServerInformation.ps1 @@ -0,0 +1,196 @@ +function Get-enADDNSServerInformation +{ + <# + .SYNOPSIS + Retrieve information about the Active Directory Domain Name Servers + + .DESCRIPTION + Retrieve information about the Active Directory Domain Name Servers + + .PARAMETER Domain + A description of the Domain parameter. + + .EXAMPLE + PS ~> Get-enADDNSServerInformation + + Retrieve information about the Active Directory Domain Name Servers, use the current domain + + .EXAMPLE + PS ~> Get-enADDNSServerInformation | Export-CSV -Path C:\scripts\PowerShell\Reports\DNS_Zones.csv -NoTypeInformation -Force -Confirm:$false + Retrieve information about the Active Directory Domain Name Servers, use the current domain and exports it to CSV + + .EXAMPLE + PS ~> Get-enADDNSServerInformation | ConvertTo-Json -Depth 10 | Set-Content -Path C:\scripts\PowerShell\Reports\DNS_Zones.json -Force -Confirm:$false + Retrieve information about the Active Directory Domain Name Servers, use the current domain and exports it to a JSON File + + .EXAMPLE + PS ~> Get-enADDNSServerInformation -Domain 'contoso.com' + + Retrieve information about the Active Directory Domain Name Servers in the Domain contoso.com + + .EXAMPLE + PS ~> Get-enADDNSServerInformation -Domain 'contoso.com', 'corp.contoso.net' + + Retrieve information about the Active Directory Domain Name Servers in the Domain contoso.com and corp.contoso.net + + .OUTPUTS + psobject + + .INPUTS + String + + .NOTES + TODO: Need refactoring: Object handler sucks + TODO: Find a non WMI based Solution for this + + Version: 1.0.1 + + GUID: 4404141a-1731-4786-8bbf-ee6706765050 + + Author: Joerg Hochwald + + Companyname: enabling Technology + + Copyright: Copyright (c) 2ß18-2019, enabling Technology - All rights reserved. + + License: https://opensource.org/licenses/BSD-3-Clause + + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + .LINK + https://www.enatec.io + + .LINK + http://msdn.microsoft.com/en-us/library/windows/desktop/aa393295(v=vs.85).aspx + + .LINK + Get-ADDomainController + + .LINK + Get-WmiObject + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [string[]] + $Domain = ([DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain().Name.ToString()) + ) + + begin + { + $DNSReport = @() + } + + process + { + foreach ($DomainEach in $Domain) + { + $AllDomainControllers = (Get-ADDomainController -Filter { + Site -like '*' -and Domain -eq $DomainEach + } | Select-Object -ExpandProperty Name) + + foreach ($SingleDomainController in $AllDomainControllers) + { + # Prevent Null Pointer Exceptions + if ($SingleDomainController) + { + # TODO: Find a non WMI based Solution for this + $Forwarders = (Get-WmiObject -ComputerName $SingleDomainController -Namespace root\MicrosoftDNS -Class MicrosoftDNS_Server -ErrorAction SilentlyContinue) + + # TODO: Find a non WMI based Solution for this + $NetworkInterface = (Get-WmiObject -ComputerName $SingleDomainController -Query 'Select * From Win32_NetworkAdapterConfiguration Where IPEnabled=TRUE' -ErrorAction SilentlyContinue) + + $DNSReport += 1 | Select-Object -Property @{ + name = 'DC' + expression = { + $SingleDomainController + } + }, @{ + name = 'Domain' + expression = { + $DomainEach + } + }, @{ + name = 'DNSHostName' + expression = { + $NetworkInterface.DNSHostName + } + }, @{ + name = 'IPAddress' + expression = { + $NetworkInterface.IPAddress + } + }, @{ + name = 'DNSServerAddresses' + expression = { + $Forwarders.ServerAddresses + } + }, @{ + name = 'DNSServerSearchOrder' + expression = { + $NetworkInterface.DNSServerSearchOrder + } + }, @{ + name = 'Forwarders' + expression = { + $Forwarders.Forwarders + } + }, @{ + name = 'BootMethod' + expression = { + $Forwarders.BootMethod + } + }, @{ + name = 'ScavengingInterval' + expression = { + $Forwarders.ScavengingInterval + } + } + } + } + } + } + + end + { + $DNSReport + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADDomainControllerInfo.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADDomainControllerInfo.ps1 new file mode 100644 index 0000000..663a19a --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADDomainControllerInfo.ps1 @@ -0,0 +1,100 @@ +Function Get-enDomainControllerInfo +{ + <# + .SYNOPSIS + Get a list of domain controllers + + .DESCRIPTION + Will provide a list of domain controllers in your current domain. + Optionally you can also request a discovery of the "closest" one. + + .PARAMETER ComputerName + Retrieve information about the specified domain controller. + This is a RegEx match so you can match multiple domain controllers with your pattern. + + .PARAMETER Discover + Use Discover to return the information of the closest domain controller. + + .EXAMPLE + Get-enDomainControllerInfo + + Retrieve a list of all domain controllers in your domain. + + .EXAMPLE + Get-enDomainControllerInfo -Computer 01 + + Retrieve a list of all domain controllers with "01" in their name. + + .EXAMPLE + Get-enDomainControllerInfo -Discover + + Retrieve the name of the closest domain controller. + + .NOTES + #> + [CmdletBinding(DefaultParameterSetName = 'all')] + Param ( + [Parameter(Position = 0, ParameterSetName = 'dc')] + [string]$ComputerName, + [Parameter(ParameterSetName = 'all')] + [switch]$Discover + ) + + begin + { + $DirectoryContext = [DirectoryServices.ActiveDirectory.DirectoryContext]::New('Domain') + $SelectProperties = 'Name', 'Forest', 'Domain', 'SiteName', 'Roles', 'CurrentTime', 'HighestCommittedUsn', 'OSVersion' + } + + process + { + If ($Discover) + { + $LocatorFlag = [DirectoryServices.ActiveDirectory.LocatorOptions]::ForceRediscovery + $Info = ([DirectoryServices.ActiveDirectory.DomainController]::FindOne($DirectoryContext, $LocatorFlag) | Select-Object -Property $SelectProperties) + } + elseif ($ComputerName) + { + $Info = ([DirectoryServices.ActiveDirectory.DomainController]::FindAll($DirectoryContext) | Where-Object -Property Name -Match -Value $ComputerName | Select-Object -Property $SelectProperties) + } + else + { + $Info = ([DirectoryServices.ActiveDirectory.DomainController]::FindAll($DirectoryContext) | Select-Object -Property $SelectProperties) + } + } + + end + { + $Info + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADFSMORole.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADFSMORole.ps1 new file mode 100644 index 0000000..979a800 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADFSMORole.ps1 @@ -0,0 +1,148 @@ +#requires -Version 3.0 -Modules ActiveDirectory + +function Get-enADFSMORole +{ + <# + .SYNOPSIS + Retrieve the FSMO Role in the Forest/Domain + + .DESCRIPTION + Retrieve the FSMO Role in the Forest/Domain of Active Directory + + .PARAMETER Credential + Specify the alternative credential to use + + .EXAMPLE + Get-enADFSMORole + + Retrieve the FSMO Role in the Forest/Domain of Active Directory + + .EXAMPLE + Get-enADFSMORole -Credential (Get-Credential) + + Retrieve the FSMO Role in the Forest/Domain of Active Directory + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + Active Directory PowerShell Module + + .LINK + https://www.enatec.io + + .LINK + Get-ADForest + + .LINK + Get-ADDomain + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [System.Management.Automation.Credential()] + [Alias('RunAs')] + [pscredential] + $Credential = [pscredential]::Empty + ) + + begin + { + $Properties = $null + } + + process + { + try + { + if ($PSBoundParameters['Credential']) + { + # Query with the credentials specified + $ForestRoles = (Get-ADForest -Credential $Credential -ErrorAction 'Stop' -ErrorVariable ErrorGetADForest) + $DomainRoles = (Get-ADDomain -Credential $Credential -ErrorAction 'Stop' -ErrorVariable ErrorGetADDomain) + } + else + { + # Query with the current credentials + $ForestRoles = (Get-ADForest) + $DomainRoles = (Get-ADDomain) + } + + # Define Properties + $Properties = @{ + SchemaMaster = $ForestRoles.SchemaMaster + DomainNamingMaster = $ForestRoles.DomainNamingMaster + InfraStructureMaster = $DomainRoles.InfraStructureMaster + RIDMaster = $DomainRoles.RIDMaster + PDCEmulator = $DomainRoles.PDCEmulator + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + $Properties + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADForestInformation.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADForestInformation.ps1 new file mode 100644 index 0000000..6e26ccf --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADForestInformation.ps1 @@ -0,0 +1,189 @@ +function Get-enADForestInformation +{ + <# + .SYNOPSIS + Retrieve information about an Active Directory Forest + + .DESCRIPTION + Retrieve information about an Active Directory Forest + + .PARAMETER ForestName + Forest name to retrieve information about + + .PARAMETER Credential + Credential to use for retrieval + + .EXAMPLE + PS ~> Get-enADForestInformation + + Retrieve information about the current Active Directory Forest + + .EXAMPLE + PS ~> Get-enADForestInformation | Select-Object ApplicationPartitions + + Retrieve information about Application Partitions from the current Active Directory Forest + + .EXAMPLE + PS ~> Get-enADForestInformation | Select-Object GlobalCatalogs + + Retrieve als Global Catalog Servers from the current Active Directory Forest + + .EXAMPLE + PS ~> (Get-enADForestInformation) | Select-Object -ExpandProperty GlobalCatalogs + + Retrieve als Global Catalog Servers from the current Active Directory Forest. More details then the above example, cause it will show all the details for each Global Catalog Servers. + + .EXAMPLE + PS ~> Get-enADForestInformation | Select-Object NamingRoleOwner + + Retrieve information about the Naming master Roles holder from the current Active Directory Forest + + .EXAMPLE + PS ~> (Get-enADForestInformation).Sites + + Retrieve information about Active Directory Sites from the current Active Directory Forest + + .EXAMPLE + PS ~> Get-enADForestInformation -Credential (Get-Credential) + + Retrieve information about the current Active Directory Forest, with special credentials (e.g. RunAs) + + .EXAMPLE + PS ~> Get-enADForestInformation -ForestName Value + + Retrieve information about Active Directory Forest specified in Value + + .EXAMPLE + PS ~> Get-enADForestInformation -ForestName Value -Credential Value + + Retrieve information about Active Directory Forest specified in Value, with special credentials (e.g. RunAs) + + .OUTPUTS + psobject + + .INPUTS + String + pscredential + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + .LINK + https://www.enatec.io + + .LINK + Get-ADForest + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('Forest')] + [string] + $ForestName = ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Name.ToString()), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [System.Management.Automation.Credential()] + [pscredential] + $Credential + ) + + begin + { + # Cleanup + $output = $null + $ActiveDirectoryContext = $null + } + + process + { + try + { + if ($Credential) + { + $credentialUser = ($Credential.UserName.ToString()) + $credentialPassword = ($Credential.GetNetworkCredential().Password.ToString()) + $ActiveDirectoryContext = (New-Object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList ('forest', $ForestName, $credentialUser, $credentialPassword)) + + # Cleanup + $credentialUser = $null + $credentialPassword = $null + } + else + { + $ActiveDirectoryContext = (New-Object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList ('forest', $ForestName)) + } + + $output = ([DirectoryServices.ActiveDirectory.Forest]::GetForest($ActiveDirectoryContext)) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + $output + + # Cleanup + $output = $null + $ActiveDirectoryContext = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADGPOReplication.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADGPOReplication.ps1 new file mode 100644 index 0000000..98de528 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADGPOReplication.ps1 @@ -0,0 +1,158 @@ +function Get-enADGPOReplication +{ + <# + .SYNOPSIS + Retrieve one or all the GPO and report their DSVersions and SysVolVersions + + .DESCRIPTION + Retrieve one or all the GPO and report their DSVersions and SysVolVersions (Users and Computers) + + .PARAMETER GPOName + Specify the name of the GPO + + .PARAMETER All + Specify that you want to retrieve all the GPO (slow if you have a lot of Domain Controllers) + + .EXAMPLE + Get-enADGPOReplication -GPOName "Default Domain Policy" + + Retrieve one GPO and report their DSVersions and SysVolVersions (Users and Computers) + + .EXAMPLE + Get-enADGPOReplication -All + + Retrieve all the GPO and report their DSVersions and SysVolVersions (Users and Computers) + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + Active Directory PowerShell Module + + .LINK + https://www.enatec.io + + .LINK + Get-ADDomainController + + .LINK + Get-GPO + #> + + [CmdletBinding(DefaultParameterSetName = 'All', + ConfirmImpact = 'None')] + param + ( + [Parameter(ParameterSetName = 'One', HelpMessage = 'Specify the name of the GPO', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('GPO')] + [String[]] + $GPOName, + [Parameter(ParameterSetName = 'All', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Switch] + $All + ) + + process + { + foreach ($DomainController in ((Get-ADDomainController -ErrorAction Stop -ErrorVariable ErrorProcessGetDC -Filter *).hostname)) + { + try + { + if ($psBoundParameters['GPOName']) + { + foreach ($GPOItem in $GPOName) + { + $GPO = (Get-GPO -Name $GPOItem -Server $DomainController -ErrorAction Stop -ErrorVariable ErrorProcessGetGPO) + + [pscustomobject][ordered] @{ + GroupPolicyName = $GPOItem + DomainController = $DomainController + UserVersion = $GPO.User.DSVersion + UserSysVolVersion = $GPO.User.SysvolVersion + ComputerVersion = $GPO.Computer.DSVersion + ComputerSysVolVersion = $GPO.Computer.SysvolVersion + } + } + } + + if ($psBoundParameters['All']) + { + $GPOList = (Get-GPO -All -Server $DomainController -ErrorAction Stop -ErrorVariable ErrorProcessGetGPOAll) + + foreach ($GPO in $GPOList) + { + [pscustomobject][ordered] @{ + GroupPolicyName = $GPO.DisplayName + DomainController = $DomainController + UserVersion = $GPO.User.DSVersion + UserSysVolVersion = $GPO.User.SysvolVersion + ComputerVersion = $GPO.Computer.DSVersion + ComputerSysVolVersion = $GPO.Computer.SysvolVersion + } + } + } + } + catch + { + Write-Warning -Message '[PROCESS] Something wrong happened' + + if ($ErrorProcessGetDC) + { + Write-Warning -Message '[PROCESS] Error while running retrieving Domain Controllers with Get-ADDomainController' + } + + if ($ErrorProcessGetGPO) + { + Write-Warning -Message '[PROCESS] Error while running Get-GPO' + } + + if ($ErrorProcessGetGPOAll) + { + Write-Warning -Message '[PROCESS] Error while running Get-GPO -All' + } + + Write-Warning -Message "[PROCESS] $($Error[0].exception.message)" + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADGroupChange.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADGroupChange.ps1 new file mode 100644 index 0000000..a26c95d --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADGroupChange.ps1 @@ -0,0 +1,210 @@ +function Get-enADGroupChange +{ + <# + .SYNOPSIS + Retrieve information about changed Active Directory groups + + .DESCRIPTION + Retrieve information about one, or more, changed Active Directory groups + + .PARAMETER Server + Active DirectoryDomain Controller to querry. + Default is the logon server + + .PARAMETER MonitorGroup + Group to monitor, multi value is supported. + Defaults to all Groups with admins. + + Specifies an Active Directory object by providing one of the following property values. The identifier in + parentheses is the LDAP display name for the attribute. + + Distinguished Name + + Example: CN=DOM-ADM,OU=groups,OU=asia,DC=corp,DC=contoso,DC=com + + GUID (objectGUID) + + Example: 599c3d2e-f72d-4d20-8a88-030d99495f20 + + The cmdlet searches the default naming context or partition to find the object. If two or more objects are + found, the cmdlet returns a non-terminating error. + + .PARAMETER Hour + Period to query, value in hours + + .EXAMPLE + Get-enADGroupChange + + Retrieve information about changed Active Directory groups + + .EXAMPLE + Get-enADGroupChange -MonitorGroup 'DOM-ADM' + + Retrieve information about changes to theActive Directory group DOM-ADM + + .EXAMPLE + Get-enADGroupChange -Server DC03 + + Retrieve information about changed Active Directory groups on DC03 + + .EXAMPLE + Get-enADGroupChange -Hour 72 + + Retrieve information about Active Directory groups that have been changed within the last 72 hours + + .EXAMPLE + Get-enADGroupChange -Server DC02 -Hour 96 + + Retrieve information about Active Directory groups that have been changed within the last 96 hours on DC02 + + .OUTPUTS + psobject + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + .INPUTS + String + Int + + .LINK + https://www.enatec.io + + .LINK + Get-ADDomainController + + .LINK + Get-ADGroup + + .LINK + Get-ADReplicationAttributeMetadata + + .LINK + Get-Date + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('DomainController')] + [string] + $Server = (Get-ADDomainController -Discover | Select-Object -ExpandProperty HostName), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('Group')] + [string[]] + $MonitorGroup = (Get-ADGroup -Filter ' AdminCount -eq 1 ' -Server $Server | Select-Object -ExpandProperty ObjectGUID), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('Period')] + [int] + $Hour = 24 + ) + + begin + { + # Create a new object + $Members = @() + + Write-Verbose -Message ('Processing group {0} via Server {1}' -f $MonitorGroup, $Server) + } + + process + { + try + { + foreach ($SingleGroup in $MonitorGroup) + { + Write-Verbose -Message ('Processing group {0}' -f $SingleGroup) + + # Querry the info and add to the Object + $Members += (Get-ADReplicationAttributeMetadata -Server $Server -Object $SingleGroup -ShowAllLinkedValues | Where-Object -FilterScript { + $_.IsLinkValue + } | Select-Object -Property @{ + name = 'GroupDN' + expression = { + $SingleGroup.DistinguishedName + } + }, @{ + name = 'GroupName' + expression = { + $SingleGroup.Name + } + }, *) + } + + # Filter + $Members | Where-Object -FilterScript { + $_.LastOriginatingChangeTime -gt (Get-Date).AddHours(-1 * $Hour) + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + $Members = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADObject.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADObject.ps1 new file mode 100644 index 0000000..42cacd3 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADObject.ps1 @@ -0,0 +1,378 @@ +function Get-enADObject +{ + <# + .SYNOPSIS + Export Active Directory Objects + + .DESCRIPTION + Export Active Directory Objects + + .PARAMETER ADObjectFilter + Provide specific AD Objects to report on. Otherwise, all AD Objects will be reported. Please review the examples provided. + + .PARAMETER DetailedReport + Provides a full report of all attributes. Otherwise, only a refined report will be given. + + .EXAMPLE + PS ~> Get-enADObject | Export-Csv C:\scripts\PowerShell\Reports\ADObjects.csv -notypeinformation -encoding UTF8 + + Export Active Directory Objects + + .EXAMPLE + PS ~> {objectclass -eq "publicFolder"} | Get-enADObject -DetailedReport | Export-Csv C:\scripts\PowerShell\Reports\PFs.csv -NoTypeInformation -Encoding UTF8 + + Export Active Directory Objects + + .EXAMPLE + PS ~> '{proxyaddresses -like "*contoso.com"}' | Get-enADObject | Export-Csv C:\scripts\PowerShell\Reports\ADObjects.csv -notypeinformation -encoding UTF8 + + Export Active Directory Objects + + .EXAMPLE + PS ~> '{proxyaddresses -like "*contoso.com"}' | Get-enADObject -DetailedReport | Export-Csv C:\scripts\PowerShell\Reports\ADObjects_Detailed.csv -notypeinformation -encoding UTF8 + + Export Active Directory Objects + + .OUTPUTS + PSObject + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + Active Directory PowerShell Module + + .LINK + https://www.enatec.io + + .LINK + Get-ADObject + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param ( + [switch] + $DetailedReport, + [Parameter(ValueFromPipeline)] + [string[]] + $ADObjectFilter + ) + + begin + { + if ($DetailedReport) + { + $Selectproperties = @( + 'DisplayName', 'UserPrincipalName', 'mail', 'CN', 'mailNickname', 'Name', 'GivenName', 'Surname', 'StreetAddress' + 'City', 'State', 'Country', 'PostalCode', 'Company', 'Title', 'Department', 'Description', 'OfficePhone' + 'MobilePhone', 'HomePhone', 'Fax', 'SamAccountName', 'DistinguishedName', 'Office', 'Enabled' + 'whenChanged', 'whenCreated', 'adminCount', 'AccountNotDelegated', 'AllowReversiblePasswordEncryption' + 'CannotChangePassword', 'Deleted', 'DoesNotRequirePreAuth', 'HomedirRequired', 'isDeleted', 'LockedOut' + 'mAPIRecipient', 'mDBUseDefaults', 'MNSLogonAccount', 'msExchHideFromAddressLists' + 'msNPAllowDialin', 'PasswordExpired', 'PasswordNeverExpires', 'PasswordNotRequired', 'ProtectedFromAccidentalDeletion' + 'SmartcardLogonRequired', 'TrustedForDelegation', 'TrustedToAuthForDelegation', 'UseDESKeyOnly', 'logonHours' + 'msExchMailboxGuid', 'replicationSignature', 'AccountExpirationDate', 'AccountLockoutTime', 'Created', 'createTimeStamp' + 'LastBadPasswordAttempt', 'LastLogonDate', 'Modified', 'modifyTimeStamp', 'msTSExpireDate', 'PasswordLastSet' + 'msExchMailboxSecurityDescriptor', 'nTSecurityDescriptor', 'BadLogonCount', 'codePage', 'countryCode' + 'deletedItemFlags', 'dLMemDefault', 'garbageCollPeriod', 'instanceType', 'msDS-SupportedEncryptionTypes' + 'msDS-User-Account-Control-Computed', 'msExchALObjectVersion', 'msExchMobileMailboxFlags', 'msExchRecipientDisplayType' + 'msExchUserAccountControl', 'primaryGroupID', 'replicatedObjectVersion', 'sAMAccountType', 'sDRightsEffective' + 'userAccountControl', 'accountExpires', 'lastLogonTimestamp', 'lockoutTime', 'msExchRecipientTypeDetails', 'msExchVersion' + 'pwdLastSet', 'uSNChanged', 'uSNCreated', 'ObjectGUID', 'objectSid', 'SID', 'autoReplyMessage', 'CanonicalName' + 'displayNamePrintable', 'Division', 'EmployeeID', 'EmployeeNumber', 'HomeDirectory', 'HomeDrive', 'homeMDB', 'homeMTA' + 'HomePage', 'Initials', 'LastKnownParent', 'legacyExchangeDN', 'LogonWorkstations' + 'Manager', 'msExchHomeServerName', 'msExchUserCulture', 'msTSLicenseVersion', 'msTSManagingLS' + 'ObjectCategory', 'ObjectClass', 'Organization', 'OtherName', 'POBox', 'PrimaryGroup' + 'ProfilePath', 'ScriptPath', 'sn', 'textEncodedORAddress', 'userParameters' + ) + + $CalculatedProps = @( + @{ + n = 'OU' + e = { + $_.DistinguishedName -replace '^.+?,(?=(OU|CN)=)' + } + }, + @{ + n = 'proxyAddresses' + e = { + ($_.proxyAddresses | Where-Object -FilterScript { + $_ -ne $null + }) -join '|' + } + }, + @{ + n = 'altRecipientBL' + e = { + ($_.altRecipientBL | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'AuthenticationPolicy' + e = { + ($_.AuthenticationPolicy | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'AuthenticationPolicySilo' + e = { + ($_.AuthenticationPolicySilo | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'Certificates' + e = { + ($_.Certificates | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'CompoundIdentitySupported' + e = { + ($_.CompoundIdentitySupported | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'dSCorePropagationData' + e = { + ($_.dSCorePropagationData | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'KerberosEncryptionType' + e = { + ($_.KerberosEncryptionType | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'managedObjects' + e = { + ($_.managedObjects | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'MemberOf' + e = { + ($_.MemberOf | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'msExchADCGlobalNames' + e = { + ($_.msExchADCGlobalNames | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'msExchPoliciesExcluded' + e = { + ($_.msExchPoliciesExcluded | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'PrincipalsAllowedToDelegateToAccount' + e = { + ($_.PrincipalsAllowedToDelegateToAccount | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'protocolSettings' + e = { + ($_.protocolSettings | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'publicDelegatesBL' + e = { + ($_.publicDelegatesBL | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'securityProtocol' + e = { + ($_.securityProtocol | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'ServicePrincipalNames' + e = { + ($_.ServicePrincipalNames | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'showInAddressBook' + e = { + ($_.showInAddressBook | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'SIDHistory' + e = { + ($_.SIDHistory | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'userCertificate' + e = { + ($_.userCertificate | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + } + ) + + $ExtensionAttribute = @( + 'extensionAttribute1', 'extensionAttribute2', 'extensionAttribute3', 'extensionAttribute4', 'extensionAttribute5' + 'extensionAttribute6', 'extensionAttribute7', 'extensionAttribute8', 'extensionAttribute9', 'extensionAttribute10' + 'extensionAttribute11', 'extensionAttribute12', 'extensionAttribute13', 'extensionAttribute14', 'extensionAttribute15' + ) + } + else + { + $Props = @( + 'DisplayName', 'UserPrincipalName', 'mail', 'CN', 'mailNickname', 'Name', 'GivenName', 'Surname', 'StreetAddress', + 'City', 'State', 'Country', 'PostalCode', 'Company', 'Title', 'Department', 'Description', 'OfficePhone' + 'MobilePhone', 'HomePhone', 'Fax', 'SamAccountName', 'DistinguishedName', 'Office', 'Enabled' + 'whenChanged', 'whenCreated', 'adminCount', 'Memberof', 'msExchPoliciesExcluded', 'proxyAddresses' + ) + + $Selectproperties = @( + 'DisplayName', 'UserPrincipalName', 'mail', 'CN', 'mailNickname', 'Name', 'GivenName', 'Surname', 'StreetAddress', + 'City', 'State', 'Country', 'PostalCode', 'Company', 'Title', 'Department', 'Description', 'OfficePhone' + 'MobilePhone', 'HomePhone', 'Fax', 'SamAccountName', 'DistinguishedName', 'Office', 'Enabled' + 'whenChanged', 'whenCreated', 'adminCount' + ) + + + $CalculatedProps = @( + @{ + n = 'proxyAddresses' + e = { + ($_.proxyAddresses | Where-Object -FilterScript { + $_ -ne $null + }) -join '|' + } + }, + @{ + n = 'OU' + e = { + $_.DistinguishedName -replace '^.+?,(?=(OU|CN)=)' + } + }, + @{ + n = 'MemberOf' + e = { + ($_.MemberOf | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + }, + @{ + n = 'msExchPoliciesExcluded' + e = { + ($_.msExchPoliciesExcluded | Where-Object -FilterScript { + $_ -ne $null + }) -join ';' + } + } + ) + } + } + + process + { + if ($ADObjectFilter) + { + foreach ($CurADObjectFilter in $ADObjectFilter) + { + if (! $DetailedReport) + { + Get-ADObject -Filter $CurADObjectFilter -Properties $Props -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps) + } + else + { + Get-ADObject -Filter $CurADObjectFilter -Properties * -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps + $ExtensionAttribute) + } + } + } + else + { + if (! $DetailedReport) + { + Get-ADObject -Filter * -Properties $Props -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps) + } + else + { + Get-ADObject -Filter * -Properties * -ResultSetSize $null | Select-Object -Property ($Selectproperties + $CalculatedProps + $ExtensionAttribute) + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADServicePrincipalName.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADServicePrincipalName.ps1 new file mode 100644 index 0000000..220a7bc --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADServicePrincipalName.ps1 @@ -0,0 +1,178 @@ +function Get-enADServicePrincipalName +{ + <# + .SYNOPSIS + Retrieves all Service Principal Names (SPNs) + + .DESCRIPTION + Retrieves all Service Principal Names (SPNs) from Active Directory + + .INPUTS + NONE + + .OUTPUTS + PSObject + + .EXAMPLE + PS /> Get-enADServicePrincipalName + + Retrieves all Service Principal Names (SPNs) from Active Directory + + .EXAMPLE + PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.ObjectClass -eq 'user' } + + Retrieves all user class Service Principal Names (SPNs) from Active Directory + + .EXAMPLE + PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.DNSHostName -like 'server01.contoso.com' } + + Retrieves all Service Principal Names (SPNs) for the Server 'server01.contoso.com' from Active Directory + + .EXAMPLE + PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.Name -like '*Krb*' } + + Retrieves all Kerberos related Service Principal Names (SPNs) from Active Directory + + .EXAMPLE + PS ~> Get-enADServicePrincipalName | Where-Object -FilterScript { $_.SPN -like '*Krb*' } + + Retrieves all Kerberos related Service Principal Names (SPNs) from Active Directory + + .EXAMPLE + PS ~> Get-enADServicePrincipalName | Export-Csv -Path C:\scripts\PowerShell\Reports\ADServicePrincipalNames.csv + + Retrieves all Service Principal Names (SPNs) from Active Directory and export them to a CSV + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + Active Directory PowerShell Module + + .LINK + https://www.enatec.io + + .LINK + Get-ADObject + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param () + + begin + { + # Create a new Object + $AllObject = @() + } + + process + { + try + { + # We use Get-ADObject because this seems to be fast enough + $paramGetADObject = @{ + Filter = "(objectClass -eq 'user') -or (objectClass -eq 'computer') -and (servicePrincipalName -like '*')" + Properties = 'Name', 'servicePrincipalName', 'DistinguishedName', 'ObjectClass', 'DNSHostName', 'whenCreated' + } + $AllServicePrincipalNames = (Get-ADObject @paramGetADObject) + + # Loop over the List we got from Get-ADObject + foreach ($SingleServicePrincipalName in $AllServicePrincipalNames) + { + # Get the values for the Service Principal Name + $ObjectClass = $SingleServicePrincipalName.ObjectClass + $DistinguishedName = $SingleServicePrincipalName.DistinguishedName + $Name = $SingleServicePrincipalName.Name + $whenCreated = $SingleServicePrincipalName.whenCreated + $DNSHostName = $SingleServicePrincipalName.DNSHostName + + # Loop over all Service Principal Names - Remeber, there could be more then one Service Principal Names value per record + foreach ($ServicePrincipalName in $SingleServicePrincipalName.servicePrincipalName) + { + # Create a new Object + $SingleObject = (New-Object -TypeName PSObject -Property @{ + Name = $Name + SPN = $ServicePrincipalName + ObjectClass = $ObjectClass + DistinguishedName = $DistinguishedName + WhenCreated = $whenCreated + DNSHostName = $DNSHostName + }) + + # Add the Values to the List + $AllObject += $SingleObject + + # Cleanup + $SingleObject = $null + } + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + # Dump + $AllObject + + # Cleanup + $AllObject = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enADSiteAndSubnet.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADSiteAndSubnet.ps1 new file mode 100644 index 0000000..0f33382 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enADSiteAndSubnet.ps1 @@ -0,0 +1,132 @@ +function Get-enADSiteAndSubnetInfo +{ + <# + .SYNOPSIS + Retrieve Site names, subnets names and descriptions. + + .DESCRIPTION + Retrieve Site names, subnets names and descriptions from the Active Directory + + .EXAMPLE + PS ~> Get-enADSiteAndSubnetInfo + + Retrieve Site names, subnets names and descriptions from the Active Directory + + .EXAMPLE + PS ~> Get-enADSiteAndSubnetInfo | Export-Csv -Path C:\scripts\PowerShell\Reports\ADSiteInventory.csv + + Retrieve Site names, subnets names and descriptions from the Active Directory + + .OUTPUTS + PSObject + + .NOTES + Releasenotes: + 1.0.1 2019-07-26 Refactored, License change to BSD 3-Clause + 1.0.0 2019-01-01 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + Active Directory PowerShell Module + + .LINK + https://www.enatec.io + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param () + + begin + { + Write-Verbose -Message '[BEGIN] Starting Script...' + } + + process + { + try + { + # Domain and Sites Information + $Forest = ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest()) + $SiteInfo = ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites) + + # Forest Context + $ForestType = ([DirectoryServices.ActiveDirectory.DirectoryContexttype]'forest') + $ForestContext = (New-Object -TypeName System.DirectoryServices.ActiveDirectory.DirectoryContext -ArgumentList $ForestType, $Forest) + + # Distinguished Name of the Configuration Partition + $Configuration = ([ADSI]'LDAP://RootDSE').configurationNamingContext + + # Get the Subnet Container + $SubnetsContainer = ([ADSI]('LDAP://CN=Subnets,CN=Sites,{0}' -f $Configuration)) + $SubnetsContainerchildren = ($SubnetsContainer.Children) + + foreach ($item in $SiteInfo) + { + Write-Verbose -Message ('[PROCESS] SITE: {0}' -f $item.name) + + $output = @{ + Name = $item.name + } + + foreach ($i in $item.Subnets.name) + { + Write-Verbose -Message ('[PROCESS] SUBNET: {0}' -f $i) + + $output.Subnet = $i + $SubnetAdditionalInfo = $SubnetsContainerchildren.Where( { + $_.name -match $i + }) + + Write-Verbose -Message ('[PROCESS] SUBNET: {0} - DESCRIPTION: {1}' -f $i, $SubnetAdditionalInfo.Description) + + $output.Description = $($SubnetAdditionalInfo.Description) + + Write-Verbose -Message '[PROCESS] OUTPUT INFO' + + New-Object -TypeName PSObject -Property $output + } + } + } + catch + { + Write-Warning -Message '[PROCESS] Something Wrong Happened' + Write-Warning -Message $Error[0] + } + } + + end + { + Write-Verbose -Message '[END] Script Completed!' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Get-enDomainInfo.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Get-enDomainInfo.ps1 new file mode 100644 index 0000000..52360a6 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Get-enDomainInfo.ps1 @@ -0,0 +1,76 @@ +Function Get-enDomainInfo +{ + <# + .SYNOPSIS + Retrieve domain information include site details + + .EXAMPLE + Get-enDomainInfo + + .NOTES + #> + [CmdletBinding()] + Param () + + begin + { + $SelectProperties = 'Name', 'Forest', 'Parent', 'Children', 'DomainMode', 'DomainModeLevel', 'DomainControllers', 'PdcRoleOwner', 'RidRoleOwner', 'InfrastructureRoleOwner', 'Sites' + } + + process + { + $CurrentDomain = [DirectoryServices.ActiveDirectory.Domain]::GetCurrentDomain() + $null = ($CurrentDomain | Add-Member -MemberType NoteProperty -Name Sites -Value ([DirectoryServices.ActiveDirectory.Forest]::GetCurrentForest().Sites)) + $Domain = ($CurrentDomain | Select-Object -Property $SelectProperties) + + <# + switch($domainModeLevel) + { + {$domainModeLevel -like "0"} {"2000 Mixed/Native"} + {$domainModeLevel -like "1"} {"2003 Interim"} + {$domainModeLevel -like "2"} {"2003"} + {$domainModeLevel -like "3"} {"2008"} + {$domainModeLevel -like "4"} {"2008 R2"} + {$domainModeLevel -like "5"} {"2012"} + {$domainModeLevel -like "6"} {"2012 R2"} + {$domainModeLevel -like "7"} {"2016"} + default {"Unknown"} + } + #> + } + + end + { + $Domain + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/LICENSE b/Powershell/PowerShell-collection/ActiveDirectory/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/ActiveDirectory/README.md b/Powershell/PowerShell-collection/ActiveDirectory/README.md new file mode 100644 index 0000000..5f635c5 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/README.md @@ -0,0 +1,7 @@ +# Legacy Notice + +I no longer run Exchange, Skype for Business, or any other Office Server on Premises. +This is my personal [reaction](https://hochwald.net/microsoft-rolls-back-decision-to-take-away-internal-usage-rights-from-partners/) to the changes that Microsoft [announced](https://hochwald.net/microsoft-is-going-to-kill-internal-use-rights-benefit-for-partners/) for the Internal Use Rights (IUR) program. I know that they decided to reverse that changes and in theory, I could still legally use the software. However, I decided to decommission everything licensed under the terms of the Internal Use Rights (IUR) program. +In my opinion, the community always should have some benefits from the Internal Use Rights (IUR) program and/or Action Pack. Now that I decided to drop out, there will be no more such benefits. + +I will _no longer maintain_ the scripts related to the Microsoft Office (on Premises) servers. They will remain here, but unmaintained. Fork the repository and maintain or extend them if you like to. The [License](https://github.com/jhochwald/PowerShell-collection/blob/master/LICENSE) allows that easily. diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Set-ADAllUserPicture.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Set-ADAllUserPicture.ps1 new file mode 100644 index 0000000..b05531d --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Set-ADAllUserPicture.ps1 @@ -0,0 +1,413 @@ +#requires -Version 3.0 -Modules ActiveDirectory + +<# + .SYNOPSIS + Tool that bulk imports or removes User pictures, based on AD Group Membership + + .DESCRIPTION + Tool that bulk imports or removes User pictures, based on AD Group Membership + If a user is in both groups, the picture will be removed! + Idea based on my old tool to import Active Directory pictures. + They are a bit to tiny, so I use Exchange now to make them look better in Exchange and Skype. + + .PARAMETER AddGroup + Active Directory Group with users that would like to have a picture. + For all Members of this group, the Tool will try to set an image. + + .PARAMETER RemGroup + Active Directory Group with users that would like have have the picture removed. + For all Members of this group, the Tool will try to remove the existing image (If set). + + .PARAMETER PictureDir + Directory that contains the pictures + + .PARAMETER Extension + Extension of the pictures + + .PARAMETER workaround + Workaround for Exchange 2016 on Windows Server 2016 + + .PARAMETER UPNDomain + The default Domain, to add to the UPN + + .EXAMPLE + # Use the Groups 'ADDPIXX' and 'NOPIXX' to Set/Remove the User Pictures + # There was an Issue with the User joerg.hochwald (Possible Picture Problem! + PS C:\> .\Set-ADAllUserPicture.ps1 -AddGroup 'ADDPIXX' -RemGroup 'NOPIXX' -PictureDir 'c:\upixx\' -workaround -UPNDomain 'jhochwald.com' + + WARNING: Unable to set Image c:\upixx\joerg.hochwald.jpg for User joerg.hochwald + + .EXAMPLE + # Use the Groups 'ADDPIXX' and 'NOPIXX' to Set/Remove the User Pictures + # There was an Issue with the User jane.doe - Check that this user has a provissioned Mailbox (on Prem or Cloud) + PS C:\> .\Set-ADAllUserPicture.ps1 -AddGroup 'ADDPIXX' -RemGroup 'NOPIXX' -PictureDir 'c:\upixx\' -workaround -UPNDomain 'jhochwald.com' + + WARNING: Unable to handle jane.doe - Check that this user has a valid Mailbox! + + .EXAMPLE + # Use the Groups 'ADDPIXX' and 'NOPIXX' to Set/Remove the User Pictures - Everything went well + PS C:\> .\Set-ADAllUserPicture.ps1 -AddGroup 'ADDPIXX' -RemGroup 'NOPIXX' -PictureDir 'c:\upixx\' -workaround -UPNDomain 'jhochwald.com' + + WARNING: Unable to handle jane.doe - Check that this user has a valid Mailbox! + + .NOTES + TODO: There is no logging! Only the Exchange RBAC logging is in use + TODO: A few error handlers are still missing + + If a user is in both groups, the picture will be removed! + Verbose could be very verbose. This is due to the fact, that the complete Exchange logging will be shown! + + There are a few possibilities for Warnings and Errors. (Mostly for missing things) + + Disclaimer: The code is provided 'as is,' with all possible faults, defects or errors, and without warranty of any kind. +#> +param +( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Active Directory Group with users that would like to have a picture')] + [ValidateNotNullOrEmpty()] + [Alias('positive')] + [string] + $AddGroup, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2, + HelpMessage = 'Active Directory Group with users that would like have have the picture removed.')] + [ValidateNotNullOrEmpty()] + [string] + $RemGroup, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 3, + HelpMessage = 'Directory that contains the picures')] + [ValidateNotNullOrEmpty()] + [Alias('PixxDir')] + [string] + $PictureDir, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 5)] + [Alias('defaultDomain')] + [string] + $UPNDomain, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 4)] + [ValidateSet('png', 'jpg', 'gif', 'bmp')] + [ValidateNotNullOrEmpty()] + [string] + $Extension = 'jpg', + [switch] + $workaround = $false +) + +begin +{ + if ($workaround) + { + # Unsupported Workaround according to https://hochwald.net/workaround-for-get-help-issue-with-exchange-2016-on-windows-server-2016/ + $null = (Add-PSSnapin -Name Microsoft.Exchange.Management.PowerShell.SnapIn) + } + + # Cleanup + $AddUserPixx = $null + $NoUserPixx = $null + + # Check the source directory string and fix it if needed + if (-not ($PictureDir).EndsWith('\')) + { + # Fix it + $PictureDir = $PictureDir + '\' + + $paramWriteVerbose = @{ + Message = 'Fixed the Source Directory String!' + } + Write-Verbose @paramWriteVerbose + } + + try + { + $paramGetADGroupMember = @{ + Identity = $AddGroup + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $AddUserPixx = (Get-ADGroupMember @paramGetADGroupMember | Select-Object -ExpandProperty samaccountname) + } + catch + { + $paramWriteError = @{ + Message = ('Unable to find {0}' -f $AddGroup) + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + return + } + + try + { + $paramGetADGroupMember = @{ + Identity = $RemGroup + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $NoUserPixx = (Get-ADGroupMember @paramGetADGroupMember | Select-Object -ExpandProperty samaccountname) + } + catch + { + $paramWriteError = @{ + Message = ('Unable to find {0}' -f $AddGroup) + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + return + } + + function Test-ValidEmail + { + <# + .SYNOPSIS + Simple Function to check if a String is a valid Mail + + .DESCRIPTION + Simple Function to check if a String is a valid Mail and return a Bool + + .PARAMETER address + Address String to Check + + .EXAMPLE + # Not a valid String + PS C:\> Test-ValidEmail -address 'Joerg.Hochwald' + False + + .EXAMPLE + # Valid String + PS C:\> Test-ValidEmail -address 'Joerg.Hochwald@outlook.com' + True + + .NOTES + Disclaimer: The code is provided 'as is,' with all possible faults, defects or errors, and without warranty of any kind. + + Author: Joerg Hochwald + #> + + [OutputType([bool])] + param + ( + [Parameter(Mandatory, + HelpMessage = 'Address String to Check')] + [ValidateNotNullOrEmpty()] + [string] + $address + ) + + process + { + ($address -as [mailaddress]).Address -eq $address -and $address -ne $null + } + } +} + +process +{ + if (-not ($AddUserPixx.samaccountname)) + { + $paramWriteVerbose = @{ + Message = ('The AD Group {0} has no members.' -f $AddGroup) + } + Write-Verbose @paramWriteVerbose + } + else + { + # Add a counter + $AddUserPixxCount = (($AddUserPixx.samaccountname).count) + + $paramWriteVerbose = @{ + Message = ('The AD Group {0} has {1} members.' -f $AddGroup, $AddUserPixxCount) + } + Write-Verbose @paramWriteVerbose + + foreach ($AddUser in $AddUserPixx.samaccountname) + { + if (($NoUserPixx.samaccountname) -notcontains $AddUser) + { + # Check the UPN and Fix it, if possible + if (-not (Test-ValidEmail -address ($AddUser))) + { + if (-not ($UPNDomain)) + { + # Whoopsie + $paramWriteError = @{ + Message = 'UPN Default Domain not set but needed!' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + } + else + { + # Let us fix this + $AddUserUPN = ($AddUser + '@' + $UPNDomain) + } + } + + # Build the Full Image Path + $SingleUserPicture = ($PictureDir + $AddUser + '.' + $Extension) + + # Check if Picture exists + $paramTestPath = @{ + Path = $SingleUserPicture + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + + if (Test-Path @paramTestPath) + { + try + { + $paramSetUserPhoto = @{ + Identity = $AddUserUPN + PictureData = ([IO.File]::ReadAllBytes($SingleUserPicture)) + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + + $null = (Set-UserPhoto @paramSetUserPhoto) + } + catch + { + $paramWriteWarning = @{ + Message = ('Unable to set Image {0} for User {1}' -f $SingleUserPicture, $AddUser) + ErrorAction = 'SilentlyContinue' + } + Write-Warning @paramWriteWarning + } + } + else + { + $paramWriteWarning = @{ + Message = ('The Image {0} for User {1} was not found' -f $SingleUserPicture, $AddUser) + ErrorAction = 'SilentlyContinue' + } + Write-Warning @paramWriteWarning + } + } + else + { + $paramWriteVerbose = @{ + Message = ('Sorry, User {0} is member of {1} and {2}' -f $AddUser, $AddGroup, $RemGroup) + } + Write-Verbose @paramWriteVerbose + } + } + } + + if (-not ($NoUserPixx.samaccountname)) + { + $paramWriteVerbose = @{ + Message = ('The AD Group {0} has no members.' -f $RemGroup) + } + Write-Verbose @paramWriteVerbose + } + else + { + # Add a counter + $NoUserPixxCount = (($NoUserPixx.samaccountname).count) + + $paramWriteVerbose = @{ + Message = ('The AD Group {0} has {1} members.' -f $RemGroup, $NoUserPixxCount) + } + Write-Verbose @paramWriteVerbose + + foreach ($NoUser in $NoUserPixx.samaccountname) + { + # Check the UPN and Fix it, if possible + if (-not (Test-ValidEmail -address ($NoUser))) + { + if (-not ($UPNDomain)) + { + # Whoopsie + $paramWriteError = @{ + Message = 'UPN Default Domain not set but needed!' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + } + else + { + # Let us fix this + $NoUserUPN = ($NoUser + '@' + $UPNDomain) + } + } + + $paramSetUserPhoto = @{ + Identity = $NoUserUPN + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + + try + { + $null = (Remove-UserPhoto @paramSetUserPhoto) + } + catch + { + $paramWriteWarning = @{ + Message = ('Unable to handle {0} - Check that this user has a valid Mailbox!' -f $NoUser) + ErrorAction = 'SilentlyContinue' + } + Write-Warning @paramWriteWarning + } + } + } +} + +end +{ + # Cleaniup + $AddUserPixx = $null + $NoUserPixx = $null + $AddUserPixxCount = $null + $NoUserPixxCount = $null + + # Do a garbage collection: Call the .NET function to cleanup some stuff + $null = ([GC]::Collect()) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ActiveDirectory/Set-ADServerUsage.ps1 b/Powershell/PowerShell-collection/ActiveDirectory/Set-ADServerUsage.ps1 new file mode 100644 index 0000000..f93ce08 --- /dev/null +++ b/Powershell/PowerShell-collection/ActiveDirectory/Set-ADServerUsage.ps1 @@ -0,0 +1,118 @@ +#requires -Version 3.0 -Modules ActiveDirectory + +function Set-ADServerUsage +{ + <# + .SYNOPSIS + Set all Active Directory related commands to use a special kind of server + + .DESCRIPTION + By default the Active Directory related commands search for a DC. By default I want to make + use of the closest one. When I make BULK operations, I would like to use the Server with + the PDC role. This becomes handy often! + + .PARAMETER pdc + Use the Active Directory Server who holds the PDC role. + + .EXAMPLE + # Use the closest Server + PS> Set-ADServerUsage + + .EXAMPLE + # Use the Server with the PDC role + PS> Set-ADServerUsage -pdc + + .EXAMPLE + # When it comes to scripts that do bulk operations, especially bulk loads and manipulation, + # I use the following within the Script: + if (Get-Command Set-ADServerUsage -ErrorAction SilentlyContinue) + { + Set-ADServerUsage -pdc + } + + .NOTES + I use this helper function in my PROFILE. Therefore, some things a bit special. + Who want's an error message every time a window opens under normal circumstances? + #> + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [switch] + $pdc + ) + + begin + { + # Defaults + $SC = 'SilentlyContinue' + + # Cleanup + $dc = $null + } + + process + { + <# + The following would do the trick: + #requires -Modules ActiveDirectory + But I don't want any error messages, so I decided to use this old-school way to figure + out if we are capable do what I want. + #> + if ((Get-Command -Name Get-ADDomain -ErrorAction $SC) -and (Get-Command -Name Get-ADDomainController -ErrorAction $SC) ) + { + if ($pdc) + { + # Use the PDC instead + $dc = ((Get-ADDomain -ErrorAction $SC -WarningAction $SC).PDCEmulator) + } + else + { + # Use the closest DC + $dc = (Get-ADDomainController -Discover -NextClosestSite -ErrorAction $SC -WarningAction $SC) + } + + # Skip everything if we do NOT have the proper information. + <# + Under normal circumstances this is pretty useless, but I use some virtual machines that have the RSAT tools installed, but they are not domain joined. + The fore I make this check. If all the systems that have the RSAT installed are domain joined, this test is obsolete. + #> + if ($dc) + { + # Make use of the Server from above + $PSDefaultParameterValues.add('*-AD*:Server', "$dc") + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/AdvancedInstaller/Invoke-AdvancedInstallerUpdate.ps1 b/Powershell/PowerShell-collection/AdvancedInstaller/Invoke-AdvancedInstallerUpdate.ps1 new file mode 100644 index 0000000..6bdf567 --- /dev/null +++ b/Powershell/PowerShell-collection/AdvancedInstaller/Invoke-AdvancedInstallerUpdate.ps1 @@ -0,0 +1,255 @@ +function Invoke-AdvancedInstallerUpdate +{ + <# + .SYNOPSIS + Sample function to rebuild a given Advanced Installer Project + + .DESCRIPTION + Rebuild a given Advanced Installer Project. + Sample script to update the build Number from our build server and create a new MSI installer. + + .PARAMETER Project + Advanced installer project name (the name of the Project file, without the AIP extension). + Example: DummyProduct for DummyProduct.aip + + .PARAMETER Path + Specifies the path to Advanced Installer Project File. + + .PARAMETER Version + Version of the new build. + + .EXAMPLE + PS C:\> Invoke-AdvancedInstallerUpdate -Project 'DummyProduct' -Path 'x:\dev\projects\DummyProduct\' -Version '1.0.3' + + .NOTES + Sample Project + + .LINK + https://www.advancedinstaller.com/user-guide/powershell-automation.html + #> + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Advanced installer project name (the name of the Project file, without the AIP extension).')] + [ValidateNotNullOrEmpty()] + [Alias('ProjectName', 'aipName')] + [string] + $Project, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Specifies the path to Advanced Installer Project File.')] + [ValidateNotNullOrEmpty()] + [Alias('aipPath')] + [string] + $Path, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2, + HelpMessage = 'Version of the new build.')] + [ValidateNotNullOrEmpty()] + [Alias('aipVersion')] + [string] + $Version + ) + + begin + { + # Create the full path of the Avanced Installer Project file + $AdvancedInstallerProjectName = $Path + $Project + '.aip' + + # Check if the File exists + if (-not (Test-Path -Path $AdvancedInstallerProjectName -ErrorAction SilentlyContinue)) + { + #region ErrorHandler + $paramWriteError = @{ + Message = ('The given File {0} was not found' -f $AdvancedInstallerProjectName) + TargetObject = $AdvancedInstallerProjectName + Category = 'ObjectNotFound' + RecommendedAction = 'Check filename' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + + # New Version number + $AdvancedInstallerProjectVersion = $Version + } + + process + { + # Cleanup + $AdvancedInstallerProject = $null + + # Creates a new PS object for Advanced Installer interaction + $AdvancedInstaller = (New-Object -ComObject AdvancedInstaller) + + # Load the Advanced Installer object + try + { + $AdvancedInstallerProject = $AdvancedInstaller.LoadProject($AdvancedInstallerProjectName) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + + if ($AdvancedInstallerProject) + { + # Modidy the version number + $AdvancedInstallerProject.ProductDetails.Version = $AdvancedInstallerProjectVersion + + try + { + # Build the project + $AdvancedInstallerProjectBuild = ($AdvancedInstallerProject.Build()) + + Write-Verbose -Message $AdvancedInstallerProjectBuild + + # Save the modified file + try + { + # Note: Remove the $null if you would like to see the output + $null = ($AdvancedInstallerProject.SaveAs($AdvancedInstallerProjectName)) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + catch + { + Write-Error -Message 'Build failed' + } + finally + { + # Cleanup + $AdvancedInstallerProject = $null + $AdvancedInstaller = $null + } + } + else + { + #region ErrorHandler + $paramWriteError = @{ + Message = ('Unable to load {0}' -f $AdvancedInstallerProjectName) + TargetObject = $AdvancedInstallerProjectName + Category = 'InvalidData' + RecommendedAction = 'Check file' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + # Create a filter for the MSI + $AdvancedInstallerProjectMSI = $Project + '.msi' + + # Cleanup + $AdvancedInstallerProjectMSIPath = $null + + # Loop over the returned object and try to find the MSI + $AdvancedInstallerProjectMSIPath = ($AdvancedInstallerProjectBuild.Split("`n") | ForEach-Object { + if ($_ -match $AdvancedInstallerProjectMSI) + { + $_ + } + }) + # TODO: The method is a bit crappy + + if ($AdvancedInstallerProjectMSIPath) + { + Write-Host -Object $AdvancedInstallerProjectMSIPath + } + else + { + Write-Warning -Message 'New MSI was not found' -WarningAction Continue + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/AdvancedInstaller/LICENSE b/Powershell/PowerShell-collection/AdvancedInstaller/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/AdvancedInstaller/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/AzureAD/Get-AzureADUserDevices.ps1 b/Powershell/PowerShell-collection/AzureAD/Get-AzureADUserDevices.ps1 new file mode 100644 index 0000000..9350cd6 --- /dev/null +++ b/Powershell/PowerShell-collection/AzureAD/Get-AzureADUserDevices.ps1 @@ -0,0 +1,199 @@ +#requires -Version 3.0 -Modules AzureAD + +<# + .SYNOPSIS + Script to monitor and return large number of user devices in Azure Active Directory. + + .DESCRIPTION + Script to monitor and return large number of user devices in Active Directory. + The default limit in Azure is 20 devices + + .PARAMETER All + If true, return all users. + + .PARAMETER HighDeviceCount + Enter the threshold for devices that you want to return + + .EXAMPLE + Get-AzureADUserDevices.ps1 -HighDeviceCount 15 -All $true + + .EXAMPLE + Get-AzureADUserDevices.ps1 -HighDeviceCount 5 -All $true + + .NOTES + Reworked version of Ben Whitmore Get-UserDevices that use the AzureAD module instead of the MsolService module + + .LINK + https://github.com/byteben/AzureAD/blob/master/Get-UserDevices.ps1 +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [int] + $HighDeviceCount = 15, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [bool] + $All +) + +begin +{ + # Defaults + $STP = 'Stop' + + # Set some default + if (-not ($HighDeviceCount)) + { + $HighDeviceCount = 15 + } + + # Connect to Azure Active Directory, if needed + if ($AzureActiveDirectoryConnection.Account -eq $null) + { + try + { + $Global:AzureActiveDirectoryConnection = (Connect-AzureAD -ErrorAction $STP) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction $STP + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + # Initialize Array to hold users and number of devices + $DeviceCountHigh = @() + + try + { + # Splatting + $paramGetAzureADUser = @{ + filter = "userType eq 'Member'" + All = $All + ErrorAction = $STP + } + + # Get list of users from Azure Active Directory + $Users = (Get-AzureADUser @paramGetAzureADUser | Select-Object -Property UserPrincipalName, ObjectId) + + # Splatting + $paramGetAzureADDevice = @{ + All = $true + ErrorAction = $STP + } + + # Get a list of Devices and the ownership information from the Azure Active Directory + $Devices = (Get-AzureADDevice @paramGetAzureADDevice | Get-AzureADDeviceRegisteredOwner -ErrorAction $STP) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction $STP + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } +} + +process +{ + foreach ($User in $Users) + { + # For each user returned, count their Registered Devices + $Device = ($Devices | Where-Object { + $_.UserPrincipalName -eq $User.UserPrincipalName + } | Measure-Object) + + # If the number of registered devices measured is high, create a new PSObject + if ($Device.Count -ge $HighDeviceCount) + { + # Create a new PSObject + $DeviceCountMember = @() + + # Fill the values + $DeviceCountMember = (New-Object -TypeName PSObject) + $DeviceCountMember | Add-Member -MemberType NoteProperty -Name 'UserPrincipalName' -Value $User.UserPrincipalName + $DeviceCountMember | Add-Member -MemberType NoteProperty -Name 'DeviceCount' -Value $Device.Count + + # Add to the PSObject + $DeviceCountHigh += $DeviceCountMember + } + } +} + +end +{ + # Display Users with high number of devices + $DeviceCountHigh | Sort-Object -Property DeviceCount -Descending +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/AzureAD/LICENSE b/Powershell/PowerShell-collection/AzureAD/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/AzureAD/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/BitLocker/Get-DsRegStatusInfo.ps1 b/Powershell/PowerShell-collection/BitLocker/Get-DsRegStatusInfo.ps1 new file mode 100644 index 0000000..fc41251 --- /dev/null +++ b/Powershell/PowerShell-collection/BitLocker/Get-DsRegStatusInfo.ps1 @@ -0,0 +1,87 @@ +#requires -Version 1.0 + +function Get-DsRegStatusInfo +{ + <# + .SYNOPSIS + Wrapper function for the dsregcmd command + + .DESCRIPTION + Wrapper function for the dsregcmd command + Nothing fancy, but it should convert the plain text output of dsregcmd to a PSObject + + .EXAMPLE + PS C:\> Get-DsRegStatusInfo + + Returns a PSObject with the values of dsregcmd + + .EXAMPLE + PS C:\> $AADInfo = (Get-DsRegStatusInfo | Select-Object -Property AzureAdJoined,WorkplaceJoined) + PS C:\> if ( ($AADInfo.AzureAdJoined -ne 'YES') -and ($AADInfo.WorkplaceJoined -ne 'YES') ) {throw 'Not AzureAD bound'} + + Check if the system is joined to the AzureAD (fully or just WorkplaceJoined) + + .EXAMPLE + PS C:\> $AADInfo = (Get-DsRegStatusInfo | Select-Object -Property AzureAdJoined, WorkplaceJoined) + PS C:\> if ($AADInfo.AzureAdJoined -eq 'YES') {'AzureAd Joined'} elseif ($AADInfo.WorkplaceJoined -eq 'YES') {'Workplace Joined'} else {'Unknown'} + + Check if the system is joined to the AzureAD (fully or just WorkplaceJoined) + + .NOTES + Replaced my old ConvertFrom-String based wrapper implementation, this is more flexible + + .LINK + http://hochwald.net + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param () + + begin + { + $DsRegCmdPlain = (& "$env:windir\system32\dsregcmd.exe" /status) + $DsRegStatusInfo = (New-Object -TypeName PSObject) + } + + process + { + $DsRegCmdPlain | Select-String -Pattern ' *[A-z]+ : [A-z]+ *' | ForEach-Object -Process { + $null = (Add-Member -InputObject $DsRegStatusInfo -MemberType NoteProperty -Name (([String]$_).Trim() -split ' : ')[0] -Value (([String]$_).Trim() -split ' : ')[1] -ErrorAction SilentlyContinue) + } + } + + end + { + $DsRegStatusInfo + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/BitLocker/Invoke-BackupBitlockerRecoveryKey.ps1 b/Powershell/PowerShell-collection/BitLocker/Invoke-BackupBitlockerRecoveryKey.ps1 new file mode 100644 index 0000000..f01c677 --- /dev/null +++ b/Powershell/PowerShell-collection/BitLocker/Invoke-BackupBitlockerRecoveryKey.ps1 @@ -0,0 +1,152 @@ +#requires -Version 2.0 -Modules BitLocker +#requires -RunAsAdministrator + +<# + .SYNOPSIS + Backup the BitLocker Recovery Information to the Azure Active Directory + + .DESCRIPTION + Backup the BitLocker Recovery Information to the Azure Active Directory + If the Boot Drive is not encrypted, the Script will try to enable the quick protection + + .EXAMPLE + PS C:\> .\Invoke-BackupBitlockerRecoveryKey.ps1 + + .EXAMPLE + PS C:\> $AADInfo = (Get-DsRegStatusInfo | Select-Object -Property AzureAdJoined,WorkplaceJoined) + PS C:\> if ( ($AADInfo.AzureAdJoined -ne 'YES') -and ($AADInfo.WorkplaceJoined -ne 'YES') ) {throw 'Not AzureAD bound'} else {.\Invoke-BackupBitlockerRecoveryKey.ps1} + + You may want to check if the device is AzureAD joined with Get-DsRegStatusInfo first + + .NOTES + Quick and relative dirty solution for a challenge I had in the last couple of days + + .LINK + Get-DsRegStatusInfo + + .LINK + http://hochwald.net +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + # Defaults + $LogName = 'Application' + $STP = 'Stop' + $SCT = 'SilentlyContinue' + $LogSource = 'enAutomate' + + # Register the event log source + $null = (New-EventLog -LogName $LogName -Source $LogSource -ErrorAction $SCT) +} + +process +{ + try + { + # Get BitLocker Volume info + $BitLockerVolumeInfo = (Get-BitLockerVolume -ErrorAction $STP | Where-Object -FilterScript { + $_.VolumeType -eq 'OperatingSystem' + }) + + # Get the Mount Point + $BootDrive = $BitLockerVolumeInfo.MountPoint + + # Check if the drive is encrypted + if ($BitLockerVolumeInfo.ProtectionStatus -ne 'On') + { + $InfoMessage = ('Enable BitLocker for ' + $BootDrive) + Write-Verbose -Message $InfoMessage + $null = (Write-EventLog -LogName $LogName -Source $LogSource -EntryType Information -EventId 1000 -Message $InfoMessage -ErrorAction $SCT) + + # Now we try to activate BitLocker (-UsedSpaceOnly is not perfect, but much faster in this case + $null = (Enable-BitLocker -MountPoint $BootDrive -EncryptionMethod XtsAes128 -UsedSpaceOnly -SkipHardwareTest -RecoveryPasswordProtector -Confirm:$false -ErrorAction $STP) + } + + # Get the correct ID (The one from the RecoveryPassword) + $BitLockerKeyProtectorId = ($BitLockerVolumeInfo.KeyProtector | Where-Object -FilterScript { + $_.KeyProtectorType -eq 'RecoveryPassword' + } | Select-Object -ExpandProperty KeyProtectorId) + + # Check if we have a recovery password/id + if ($BitLockerKeyProtectorId) + { + # Do the backup towards AzureAD + $null = (BackupToAAD-BitLockerKeyProtector -MountPoint $BootDrive -KeyProtectorId $BitLockerKeyProtectorId -Confirm:$false -ErrorAction $STP) + + $InfoMessage = ('The Recovery Infor for ' + $BootDrive + ' was saved to the Azure Active Directory') + Write-Verbose -Message $InfoMessage + $null = (Write-EventLog -LogName $LogName -Source $LogSource -EntryType Information -EventId 1000 -Message $InfoMessage -ErrorAction $SCT) + } + else + { + $WarningMessage = ('No Recorvery Information for ' + $BootDrive + ' found...') + Write-Warning -Message $WarningMessage + $null = (Write-EventLog -LogName $LogName -Source $LogSource -EntryType Warning -EventId 1001 -Message $WarningMessage -ErrorAction $SCT) + } + } + catch + { + #region ErrorHandler + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Error Stack + $info | Out-String | Write-Verbose + + # Save to the Event Log + $null = (Write-EventLog -LogName $LogName -Source $LogSource -EntryType Error -EventId 1001 -Message ($info.Exception) -ErrorAction $SCT) + + # Just display the info on continue with the rest of the list + $paramWriteError = @{ + Message = ($info.Exception) + Exception = $info.Exception + TargetObject = $info.Target + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + Write-Error @paramWriteError + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/BitLocker/LICENSE b/Powershell/PowerShell-collection/BitLocker/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/BitLocker/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/BitLocker/New-BitlockerRecoveryKey.ps1 b/Powershell/PowerShell-collection/BitLocker/New-BitlockerRecoveryKey.ps1 new file mode 100644 index 0000000..f3f73ee --- /dev/null +++ b/Powershell/PowerShell-collection/BitLocker/New-BitlockerRecoveryKey.ps1 @@ -0,0 +1,144 @@ +#requires -Version 2.0 -Modules BitLocker +#requires -RunAsAdministrator + +<# + .SYNOPSIS + Create a new BitLocker Recovery Key + + .DESCRIPTION + Create a new BitLocker Recovery Key + We will just create a new one, but we will not show it. + You should store it into the AzureAD, or a least in the Active Directory + + .EXAMPLE + PS C:\> .\New-BitlockerRecoveryKey.ps1 + + .NOTES + Quick and relative dirty solution for a challange I had in the last couple of days + By the way: Only the Boot Drive is supported by default. + + .LINK + Add-BitLockerKeyProtector + + .LINK + http://hochwald.net +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + # Defaults + $LogName = 'Application' + $STP = 'Stop' + $SCT = 'SilentlyContinue' + $LogSource = 'enAutomate' + + # Register the event log source + $null = (New-EventLog -LogName $LogName -Source $LogSource -ErrorAction $SCT) +} + +process +{ + # Get BitLocker Volume info + $BitLockerVolumeInfo = (Get-BitLockerVolume | Where-Object -FilterScript { + $_.VolumeType -eq 'OperatingSystem' + }) + + # Get the Mount Point + $BootDrive = $BitLockerVolumeInfo.MountPoint + + # Get the Key + $KeyProtectors = $BitLockerVolumeInfo.KeyProtector + + # Check if the Boot Drive is encrypted + if (($BitLockerVolumeInfo.VolumeStatus -eq 'FullyDecrypted') -or ($BitLockerVolumeInfo.ProtectionStatus -eq 'Off') -or (-not ($KeyProtectors))) + { + Write-Warning -Message ('Please Exceute: "Enable-BitLocker -MountPoint {0}"' -f $BootDrive) + break + } + else + { + foreach ($KeyProtector in $KeyProtectors) + { + if ($KeyProtector.KeyProtectorType -eq 'RecoveryPassword') + { + try + { + # Remove the existing Recovery Password + $null = (Remove-BitLockerKeyProtector -MountPoint $BootDrive -KeyProtectorId $KeyProtector.KeyProtectorId -ErrorAction $STP) + + # Just add a new Recovery Password without showing it here. We store than in the AzureAD anyway! + $null = (Add-BitLockerKeyProtector -MountPoint $BootDrive -RecoveryPasswordProtector -WarningAction SilentlyContinue) + + # If we get this far, eveything has worked, write a success to the event log + $InfoText = 'Changed the BitLocker Recovery Password for ' + $BootDrive + ' successfully' + Write-EventLog -LogName $LogName -Source $LogSource -EntryType Information -EventId 1000 -Message $InfoText + Write-Output -InputObject $InfoText + } + catch + { + #region ErrorHandler + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Error Stack + $info | Out-String | Write-Verbose + + # Save to the Event Log + $null = (Write-EventLog -LogName $LogName -Source $LogSource -EntryType Error -EventId 1001 -Message ($info.Exception) -ErrorAction $SCT) + + # Just display the info on continue with the rest of the list + $paramWriteError = @{ + Message = ($info.Exception) + Exception = $info.Exception + TargetObject = $info.Target + ErrorAction = $STP + WarningAction = 'Continue' + } + Write-Error @paramWriteError + } + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Exchange/CleanupExchangeLogs.ps1 b/Powershell/PowerShell-collection/Exchange/CleanupExchangeLogs.ps1 new file mode 100644 index 0000000..411d896 --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/CleanupExchangeLogs.ps1 @@ -0,0 +1,420 @@ +#requires -Version 2.0 + +<# + .SYNOPSIS + Exchange Server Logs Cleanup + + .DESCRIPTION + Cleanup some Exchange Server logs. + + .EXAMPLE + PS C:\> .\CleanupExchangeLogs.ps1 + + .NOTES + Releasenotes: + 1.0.1 2019-07-08: Move the delete process to the dedicated Invoke-CleanupOldFiles function + 1.0.0 2019-02-04: Internal Release + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + .LINK + Invoke-CleanupOldFiles +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + # You can change the number of days here + $days = 30 + + #region PowerShell2WorkArounds + <# + The following stuff is a workaround to make everything compatible to PowerShell 2.0 + Old, but some still have the old crap on the Exchange server running, sorry! + #> + #region RequiredModuleWorkAround + if (Get-Module -Name webadministration -ListAvailable -ErrorAction SilentlyContinue) + { + try + { + $null = (Import-Module -Name webadministration -Force -ErrorAction Stop) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + else + { + #region ErrorHandler + $paramWriteError = @{ + Message = 'The required Module (webadministration) is missing!' + Category = 'ObjectNotFound' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + #endregion RequiredModuleWorkAround + + #region RunAsAdministrator + function Test-Administrator + { + <# + .SYNOPSIS + Check if this is an elevated shell + + .DESCRIPTION + Check if this is an elevated shell. + + In Powershell 4.0 it can be replaced with: + #Requires -RunAsAdministrator + + .EXAMPLE + PS C:\> Test-Administrator + + .NOTES + In Powershell 4.0 it can be replaced with: Requires -RunAsAdministrator + + License: Public Domain + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([bool])] + param () + + process + { + $user = [Security.Principal.WindowsIdentity]::GetCurrent() + (New-Object -TypeName Security.Principal.WindowsPrincipal -ArgumentList $user).IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) + } + } + + if ((Test-Administrator) -ne $true) + { + #region ErrorHandler + Write-Error -Message 'The current Windows PowerShell session is not running as Administrator. Start Windows PowerShell by using the Run as Administrator option, and then try running the script again.' -Category NotEnabled -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + #endregion RunAsAdministrator + #endregion PowerShell2WorkArounds + + # Cleanup + $LogDirList = $null + + # Create a new List + $LogDirList = (New-Object -TypeName System.Collections.Generic.List[System.Object]) + + # Add static Directories to the new list + if ($env:ExchangeInstallPath) + { + $LogDirList.Add($env:ExchangeInstallPath + 'Logging\') + + # Another possible Directory + #$LogDirList.Add($env:ExchangeInstallPath + 'Bin\Search\Ceres\Diagnostics\Logs\') + } + else + { + Write-Warning -Message 'This is not a Exchange Server!' + } + + # Get a list of all IIS Websites and add to the new list + $AllIISSites = (Get-Website) + + if ($AllIISSites) + { + # Loop over the IIS Site list + foreach ($SingleWebSite in $AllIISSites) + { + # Cleanup + $IISLogDirectory = $null + + # Get the Log-Directory from the IIS Info + $IISLogDirectory = ($SingleWebSite.logfile.directory) + + <# + Replace the returned %SystemDrive% with your system drive. + This is your BOOT Drive!!! Usually it is C: + #> + if ($IISLogDirectory -match '%SystemDrive%') + { + Write-Verbose -Message 'Mangle the SystemDrive within the variable...' + + $IISLogDirectory = ($IISLogDirectory -replace '%SystemDrive%', 'C:') + } + + # Add the log Directory to the List + $LogDirList.Add($IISLogDirectory) + } + } + else + { + Write-Warning -Message 'No IIS Log-Directory found!' + } + + # Make all entries in the List unique + $LogDirList = ($LogDirList | Sort-Object | Get-Unique) + + #region Invoke-CleanupOldFiles + function Invoke-CleanupOldFiles + { + <# + .SYNOPSIS + Remove files older then a given number of days + + .DESCRIPTION + Remove files older then a given number of days. + Mostly used within cleanup Tasks. + + .PARAMETER Path + Path to search. + + .PARAMETER Age + Age of files to remove, in days. + Defaults to 30 + + .EXAMPLE + PS C:\> Invoke-CleanupoldFiles -Path 'C:\inetpub\logs\LogFiles' + + .EXAMPLE + PS C:\> Invoke-CleanupoldFiles -Path 'C:\inetpub\logs\LogFiles' -Age 14 + + .NOTES + Releasenotes: + 1.0.1 2019-07-08: Rework and splatting + 1.0.0 2019-02-04: Internal Release + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + .LINK + Get-ChildItem + + .LINK + Test-Path + + .LINK + Get-Date + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param + ( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 0, + HelpMessage = 'Path to search.')] + [ValidateNotNullOrEmpty()] + [Alias('TargetFolder')] + [string] + $Path, + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 1)] + [ValidateNotNullOrEmpty()] + [Alias('Days')] + [int] + $Age = 30 + ) + + process + { + if (Test-Path -Path $Path) + { + # Save the date to use it for the compare + $Now = (Get-Date) + + # Today minus given days + $LastWrite = $Now.AddDays(-$days) + + # Splatting the parameters + $paramGetChildItem = @{ + Path = $Path + Include = '*.log', '*.blg' + Recurse = $true + } + + # Find all Files to Delete (e.g. older then the given value) + $Files = (Get-ChildItem @paramGetChildItem | Where-Object -FilterScript { + (-not ($_.PSIsContainer)) -and ($_.LastWriteTime -le $LastWrite) + } | Select-Object -ExpandProperty fullname) + + # Loop over the list of Files + foreach ($File in $Files) + { + # Support for WhatIf and Verbose + if ($pscmdlet.ShouldProcess($File, 'Remove')) + { + # Splatting the parameters + $paramRemoveItem = @{ + Path = $File + ErrorAction = 'SilentlyContinue' + Force = $true + WhatIf = $false + } + # Remove the files that we found + $null = (Remove-Item @paramRemoveItem) + } + } + } + else + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + } + #endregion Invoke-CleanupOldFiles +} + +process +{ + # Do we have a lif of directories? + if ($LogDirList) + { + # Loop over the List of Directories + foreach ($LogDir in $LogDirList) + { + Write-Verbose -Message "Removing logs from $LogDir older then $days days" + + try + { + # Do we have a DAY value + if ($days) + { + # Splatting the parameters + $paramInvokeCleanupoldFiles = @{ + Path = $LogDir + Age = $days + ErrorAction = 'Stop' + verbose = $true + } + } + else + { + # Splatting the parameters + $paramInvokeCleanupoldFiles = @{ + Path = $LogDir + ErrorAction = 'Stop' + verbose = $true + } + } + + # Invoke the internal Fun + Invoke-CleanupOldFiles @paramInvokeCleanupoldFiles + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + } + else + { + #region ErrorHandler + $paramWriteError = @{ + Message = 'No directories found to cleanup' + Category = 'ObjectNotFound' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Exchange/Clear-LogFileDirectory.ps1 b/Powershell/PowerShell-collection/Exchange/Clear-LogFileDirectory.ps1 new file mode 100644 index 0000000..bfe93f2 --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/Clear-LogFileDirectory.ps1 @@ -0,0 +1,219 @@ +#requires -Version 3.0 -RunAsAdministrator +<# + .SYNOPSIS + Cleanup some of the Exchange Logs + + .DESCRIPTION + Cleanup some of the Exchange Logs + + .EXAMPLE + PS C:\> .\Clear-LogFileDirectory.ps1 + + .NOTES + Wrapper for the Clear-LogFileDirectory function + Everything is hardcoded for this wrapper ;-) + + .LINK + Clear-LogFileDirectory +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +# Files older then 1 day are deleted +$Days = 1 + +# Exchange Base Directory +$ExchangeBaseDir = 'D:\Exchange Server' + +# Exchange Version (Directory) +$ExchangeVersion = 'V15' + +# Where to find the IIS stuff +$IISBaseDir = "$env:HOMEDRIVE\inetpub" + + +#region IIS +# Append the Log Stuff for the Call below +$IISLogPath = $IISBaseDir + '\logs\LogFiles\' +#endregion IIS + +#region Exchange +# Combine the values +$ExchangeDirectoryPath = $ExchangeBaseDir + '\' + $ExchangeVersion + +# Append the Log Stuff for the Call below +$ExchangeLoggingPath = $ExchangeDirectoryPath + '\Logging\' +$ExchangeETLTraces = $ExchangeDirectoryPath + '\Bin\Search\Ceres\Diagnostics\ETLTraces\' +$ExchangeETLLogs = $ExchangeDirectoryPath + '\Bin\Search\Ceres\Diagnostics\Logs' +#endregion Exchange + +#region HelperFunction +function Clear-LogFileDirectory +{ + <# + .SYNOPSIS + Cleanup Files in a given Directory + + .DESCRIPTION + Cleanup Files in a given Directory + + .PARAMETER Path + Specifies a path, multi-value or wildcards are not yet supported! + No default so far! + + .PARAMETER Days + Age of the Files to Delete. + Default is 7 + + .EXAMPLE + PS C:\> Clear-LogFileDirectory -Path "c:\inetpub\logs\LogFiles\" + + .NOTES + Mind the Gap: + Everything within the given directory will be deleted, without any further interaction! + #> + + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'Specifies a path, multivalue or wildcards are not yet supported!')] + [ValidateNotNullOrEmpty()] + [Alias('Folder', 'TargetFolder')] + [string] + $Path, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('Age', 'FileAge')] + [int] + $Days = 7 + ) + + begin + { + #region Defaults + $CNT = 'Continue' + $SCT = 'SilentlyContinue' + #endregion Defaults + + Write-Verbose -Message ('START: Processing of {0}' -f $Path) + } + + process + { + if (Test-Path -Path $Path -ErrorAction $SCT) + { + $Now = (Get-Date) + $LastWrite = $Now.AddDays(-$Days) + + #region FindAndFilterFiles + # Splat the Parameters + $paramFindAndFilterFiles = @{ + Path = $Path + Recurse = $true + ErrorAction = $SCT + } + $Files = (Get-ChildItem @paramFindAndFilterFiles | Where-Object -FilterScript { + ($_.Name -like '*.log') -or ($_.Name -like '*.blg') -or ($_.Name -like '*.etl') + } | Where-Object -FilterScript { + $_.lastWriteTime -le $LastWrite + } | Select-Object -ExpandProperty FullName) + #endregion FindAndFilterFiles + + #region FileLooper + foreach ($File in $Files) + { + Write-Verbose -Message ('Deleting file {0}' -f $File) + try + { + if ($pscmdlet.ShouldProcess($File, 'Delete')) + { + #region DeleteFilesFound + # Splat the Parameters + $paramDeleteFilesFound = @{ + Path = $File + Force = $true + Confirm = $false + ErrorAction = 'Stop' + } + $null = (Remove-Item @paramDeleteFilesFound) + #endregion DeleteFilesFound + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message ($info.Exception) -ErrorAction $CNT -WarningAction $CNT + #endregion ErrorHandler + } + } + #endregion FileLooper + } + else + { + Write-Error -Message ("The folder {0} doesn't exist! Check the folder path!" -f $Path) + } + } + + end + { + Write-Verbose -Message ('DONE: Processed {0}' -f $Path) + } +} +#endregion HelperFunction + +#region FunctionWrapper +Clear-LogFileDirectory -Path $IISLogPath -Days $Days +Clear-LogFileDirectory -Path $ExchangeLoggingPath -Days $Days +Clear-LogFileDirectory -Path $ExchangeETLTraces -Days $Days +Clear-LogFileDirectory -Path $ExchangeETLLogs -Days $Days +#endregion FunctionWrapper + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Exchange/Enable-ModernAuth-Exchange.ps1 b/Powershell/PowerShell-collection/Exchange/Enable-ModernAuth-Exchange.ps1 new file mode 100644 index 0000000..08a8137 --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/Enable-ModernAuth-Exchange.ps1 @@ -0,0 +1,91 @@ +#requires -Version 2.0 + +<# + .SYNOPSIS + Enabling Modern Authentication for Exchange Online + + .DESCRIPTION + Enabling Modern Authentication for Exchange Online (Office 365) + + .EXAMPLE + PS C:\> .\Enable-ModernAuth-Exchange.ps1 + + .NOTES + Works fine with Office 2013 and Office 2016 on Windows. Tested with Office 2016 on the Mac. + You must enable it on your computers (Windows and Mac) as well! It is disabled by default. + + .LINK + https://blogs.technet.microsoft.com/canitpro/2015/09/11/step-by-step-setting-up-ad-fs-and-enabling-single-sign-on-to-office-365/ +#> +[CmdletBinding()] +param () + +begin +{ + # The Exchange Online URL + $ExoURL = 'https://outlook.office365.com/powershell-liveid/' + + # Same as above, but for the German Office 365 (MCD) + #$ExoURL = 'https://outlook.office.de/powershell-liveid/' + + # The Exchange Online Authentication method + $ExoAuth = 'Basic' +} + +process +{ + # Get the Credentials (Could also be imported if you have dem saved) + $credentials = (Get-Credential) + + # Create the new session + $paramNewPSSession = @{ + ConfigurationName = 'Microsoft.Exchange' + ConnectionUri = $ExoURL + Credential = $credentials + Authentication = $ExoAuth + AllowRedirection = $true + } + $ExoSession = (New-PSSession @paramNewPSSession) + + # Start the Session by importing it to the PowerShell Session + $null = (Import-PSSession -Session $ExoSession) + + # Enable Modern Authentication, use $false to disable it + $null = (Set-OrganizationConfig -OAuth2ClientProfileEnabled $true) +} + +end +{ + # Cleanup + $ExoSession = $null +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Exchange/Get-ADExchangeServers.ps1 b/Powershell/PowerShell-collection/Exchange/Get-ADExchangeServers.ps1 new file mode 100644 index 0000000..9f9c298 --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/Get-ADExchangeServers.ps1 @@ -0,0 +1,226 @@ +function Get-ADExchangeServers +{ + <# + .SYNOPSIS + Get all Exchange Servers from Active Directory + + .DESCRIPTION + This function gets a list with info of all Exchange Servers from the Active Directory. + The Exchange tools (or a PowerShell Connection) is not needed. + That is the major difference to Get-ExchangeServer + + .EXAMPLE + # Get all Exchange Servers from Active Directory + PS> Get-ADExchangeServers + + path : http://nycexch01.contoso.com/powershell + server : NYCEXCH01 + Fullver : Version 15.1 (Build 31034.26) + version : 15.1 + Site : HQ + + path : http://nycexch02.contoso.com/powershell + server : NYCEXCH02 + Fullver : Version 15.1 (Build 31034.26) + version : 15.1 + Site : HQ + + .EXAMPLE + # No Exchange Server found! (Error) + PS> Get-ADExchangeServers + + Get-ADExchangeServers : Unable to get the Exchange Information from the Active Directory! + + .NOTES + Only Exchange Servers with a configured PowerShell URI will be dumped + #> + [CmdletBinding()] + [OutputType([psobject])] + param () + + begin + { + # Define some defaults + $ErrorMessage = 'Unable to get the Exchange Information from the Active Directory!' + $SC = 'SilentlyContinue' + $STP = 'Stop' + + # Search configuration partition for Exchange Servers where the powershell virtual directory is enabled + try + { + $ActiveDirectoryInfo = (New-Object -TypeName adsisearcher -ArgumentList ([adsi]"LDAP://$(([adsi]'LDAP://rootdse').configurationNamingContext)"), '(&(objectclass=msExchPowerShellVirtualDirectory)(msexchinternalhostname=*))') + } + catch + { + $paramWriteError = @{ + Message = $ErrorMessage + ErrorAction = $STP + WarningAction = $SC + } + + Write-Error @paramWriteError + break + } + + if (-not ($ActiveDirectoryInfo)) + { + $paramWriteError = @{ + Message = $ErrorMessage + ErrorAction = $STP + WarningAction = $SC + } + + Write-Error @paramWriteError + break + } + + # Create a new Object + $ADExchangeInfo = @() + } + + process + { + try + { + $ActiveDirectoryInfo.findall() | Sort-Object -Descending -Property { + $_.properties.msexchversion[0] + } | ForEach-Object -Process { + # Define some defauts + $NONE = ' ' + $COM = ',' + + if ($_.properties.msexchinternalhostname[0]) + { + if ($_.properties.distinguishedname[0]) + { + $SrvLdapPath = ($_.properties.distinguishedname[0] -split $COM)[3 .. 100] -join $COM + + try + { + $SingleServerObject = [adsi]"LDAP://$SrvLdapPath" + } + catch + { + $SingleServerObject = $null + } + + if ($SingleServerObject) + { + if ($SingleServerObject.serialnumber[0]) + { + $SingleFullVersion = $SingleServerObject.serialnumber[0] + } + else + { + $SingleFullVersion = $null + } + + if (($SingleServerObject.serialNumber -split $NONE)[1]) + { + $SingleShortVersion = ($SingleServerObject.serialNumber -split $NONE)[1] + } + else + { + $SingleShortVersion = $null + } + + if ($SingleServerObject.name[0]) + { + $SingleServer = $SingleServerObject.name[0] + } + else + { + $SingleServer = $null + } + + if ($SingleServerObject.msExchServerSite[0]) + { + $SingleActiveDirectorySite = $SingleServerObject.msExchServerSite[0] -replace '^CN=|,.*$', '' + } + else + { + $SingleActiveDirectorySite = $null + } + } + + if ($_.properties.msexchinternalhostname[0]) + { + # With each virtual directory create an object to represent its details, + # if List Version or site is included, also find the server object + $paramNewObject = @{ + TypeName = 'psobject' + Property = @{ + path = $_.properties.msexchinternalhostname[0] + server = $SingleServer + Site = $SingleActiveDirectorySite + version = $SingleShortVersion + Fullver = $SingleFullVersion + } + } + + $SingleExchangeInfo = (New-Object @paramNewObject) + + # Append the Info to the Object + $ADExchangeInfo += $SingleExchangeInfo + } + } + } + } + } + catch + { + # Do nothing + Write-Verbose -Message 'Something went wrong...' + } + } + + end + { + # Just dump the plain object + if ($ADExchangeInfo) + { + $ADExchangeInfo + } + else + { + $paramWriteError = @{ + Message = $ErrorMessage + ErrorAction = $STP + WarningAction = $SC + } + + Write-Error @paramWriteError + break + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Exchange/Get-HafniumReports.ps1 b/Powershell/PowerShell-collection/Exchange/Get-HafniumReports.ps1 new file mode 100644 index 0000000..15d75ef --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/Get-HafniumReports.ps1 @@ -0,0 +1,91 @@ +<# + .SYNOPSIS + Helper script to investigate a Hafnium attack + + .DESCRIPTION + Helper script to investigate a Hafnium attack + + .PARAMETER ReportPath + Where to save the reports + + .EXAMPLE + PS C:\> .\Get-HafniumReports.ps1 + + .LINK + https://discuss.elastic.co/t/detection-and-response-for-hafnium-activity/266289 + + . LINK + https://www.msxfaq.de/exchange/update/hafnium-nachbereitung.htm + + .NOTES + This does NOT replace a Anti Virus scanner and also does NOT replace the Microsoft investigation scripts! + You can use this to bring your ongoing security investigation(s) a step forward, not more but not less. +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [ValidateNotNull()] + [Alias('Path')] + [string] + $ReportPath = 'C:\scripts\PowerShell\reports\Hafnium\' +) + +begin +{ + # Create the report directory, if needed + if (-not (Test-Path -Path $ReportPath -ErrorAction SilentlyContinue)) + { + $null = (New-Item -Path $ReportPath -ItemType Directory -Force -ErrorAction Stop) + } + + # Create a Timestamp + $TimeStamp = (Get-Date -Format 'yyyyMMdd_HHmmss') +} + +process +{ + <# + Look for commands like "Set-OABVirtualDirectory" - This is one of the known commands that the attackers used. + #> + + # Get Exchange Event Logs + $null = (Get-WinEvent -LogName 'MSExchange Management' -ErrorAction SilentlyContinue | Export-Csv -Path ($ReportPath + 'MSExchangeManagement_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8 -ErrorAction SilentlyContinue) + + <# + Look for tasks that you don't know. + "WwanSvcdcs" is one of the names that are known as related to Hafnium + + Please keep in mind: Windows itself use Scheduled Tasks a lot! + #> + + # Get Scheduled Task info + $null = (Get-ScheduledTask -ErrorAction SilentlyContinue | Select-Object -Property actions -ExpandProperty actions -ErrorAction SilentlyContinue | Export-Csv -Path ($ReportPath + 'ScheduledTaskInfo_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8 -ErrorAction SilentlyContinue) + + <# + See above, and watch for tasks that are created since January 2021 that you can not identify. + + Please keep in mind: Windows itself use Scheduled Tasks a lot! + #> + + # TaskScheduler info + $null = (Get-WinEvent -LogName 'Microsoft-Windows-TaskScheduler/Operational' -ErrorAction SilentlyContinue | Export-Csv -Path ($ReportPath + 'TaskScheduler_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8 -ErrorAction SilentlyContinue) + + <# + PowerShell keeps a history that will be saved into a plain ASC File. At least if the ReadLine Module is installed! + A bit work, but you can at least try to identify something strange here! + #> + + # Get all History Files from PowerShell + $null = (Get-ChildItem -Path 'C:\Users' -Filter 'ConsoleHost_history.txt' -Recurse -ErrorAction SilentlyContinue -Force | ForEach-Object -Process { + $null = (Get-Content -Path $_.FullName -ErrorAction SilentlyContinue | Out-File -FilePath ($ReportPath + 'PowerShell_History_' + $TimeStamp + '.txt') -Encoding utf8 -Append -ErrorAction SilentlyContinue) + }) +} + +end +{ + # Open the directory in the File Explorer + Invoke-Item -Path $ReportPath +} diff --git a/Powershell/PowerShell-collection/Exchange/LICENSE b/Powershell/PowerShell-collection/Exchange/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Exchange/README.md b/Powershell/PowerShell-collection/Exchange/README.md new file mode 100644 index 0000000..d7338b1 --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/README.md @@ -0,0 +1,8 @@ +# Legacy Notice + +I no longer run Exchange, Skype for Business, or any other Office Server on Premises. +This is my personal [reaction](https://hochwald.net/microsoft-rolls-back-decision-to-take-away-internal-usage-rights-from-partners/) to the changes that Microsoft [announced](https://hochwald.net/microsoft-is-going-to-kill-internal-use-rights-benefit-for-partners/) for the Internal Use Rights (IUR) program. I know that they decided to reverse that changes and in theory, I could still legally use the software. However, I decided to decommission everything licensed under the terms of the Internal Use Rights (IUR) program. +In my opinion, the community always should have some benefits from the Internal Use Rights (IUR) program and/or Action Pack. Now that I decided to drop out, there will be no more such benefits. + +I will _no longer maintain_ the scripts related to the Microsoft Office (on Premises) servers. They will remain here, but unmaintained. Fork the repository and maintain or extend them if you like to. The [License](https://github.com/jhochwald/PowerShell-collection/blob/master/LICENSE) allows that easily. + diff --git a/Powershell/PowerShell-collection/Exchange/Remove-AntiSpamAgents.ps1 b/Powershell/PowerShell-collection/Exchange/Remove-AntiSpamAgents.ps1 new file mode 100644 index 0000000..b372dd5 --- /dev/null +++ b/Powershell/PowerShell-collection/Exchange/Remove-AntiSpamAgents.ps1 @@ -0,0 +1,109 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Uninstalls the old and retired Anti-spam Agents from an Exchange Server + + .DESCRIPTION + Microsoft announced that they deprecated the support for the SmartScreen Anti-spam content filters for Exchange Servers. This script uninstalls the old an retired SmartScreen Anti-spam Agents from the local Exchange Server. + This is an easy to use and light weight replacement for Uninstall-AntiSpamAgents.ps1 from the \Scripts of your Exchange Installation, it will remove just the dead parts and leave the rest as it is. Some find that it might be better to leave the rest intact. + + .EXAMPLE + PS C:\> Remove-AntiSpamAgents + + .NOTES + Find a suitable an solid replacement solution for your email hygiene. This could be any 3rd party solution on premise or cloud. Never use email without any good email hygiene! + + If you want, you might run the Uninstall-AntiSpamAgents.ps1 from the \Scripts folder created by Setup during Exchange installation. It removes everything related to the AntiSpamAgents. + + Taken from the links below. + + .LINK + https://blogs.technet.microsoft.com/exchange/2016/09/01/deprecating-support-for-smartscreen-in-outlook-and-exchange/ + + .LINK + https://blogs.technet.microsoft.com/exchange/2017/03/23/exchange-server-edge-support-on-windows-server-2016-update/ +#> +[CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess = $true)] +param () + +begin +{ + # Constants + $STP = 'SilentlyContinue' + + # Agents to remove + $TransportAgentsToRemove = 'Content Filter Agent', 'Sender Id Agent', 'Protocol Analysis Agent' +} + +process +{ + # Loop over the List + foreach ($TransportAgentToRemove in $TransportAgentsToRemove) + { + # Do we have the agent we would like to remove? + if (Get-TransportAgent -Identity $TransportAgentToRemove -ErrorAction $STP -WarningAction $STP) + { + Write-Verbose -Message "Try to remove $TransportAgentToRemove" + + try + { + # Do it, or dry run it? + if ($pscmdlet.ShouldProcess("$TransportAgentToRemove", 'Remove TransportAgent')) + { + # Remove it... + $paramUninstallTransportAgent = @{ + Identity = $TransportAgentToRemove + ErrorAction = $STP + WarningAction = $STP + Confirm = $false + } + $null = (Uninstall-TransportAgent @paramUninstallTransportAgent) + } + } + catch + { + # Whoopsss + Write-Warning -Message "Unable to remove $TransportAgentToRemove" + } + + Write-Verbose -Message "$TransportAgentToRemove was removed" + } + else + { + Write-Verbose -Message "Sorry, $TransportAgentToRemove was not found..." + } + } + +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ExchangeNodeMaintenanceMode/readme.md b/Powershell/PowerShell-collection/ExchangeNodeMaintenanceMode/readme.md new file mode 100644 index 0000000..84e838b --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeNodeMaintenanceMode/readme.md @@ -0,0 +1,3 @@ +# ExchangeNodeMaintenanceMode + +New location: [https://github.com/jhochwald/ExchangeNodeMaintenanceMode](https://github.com/jhochwald/ExchangeNodeMaintenanceMode) diff --git a/Powershell/PowerShell-collection/ExchangeOnline/Approve-CASMailboxSettings.ps1 b/Powershell/PowerShell-collection/ExchangeOnline/Approve-CASMailboxSettings.ps1 new file mode 100644 index 0000000..c141f29 --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/Approve-CASMailboxSettings.ps1 @@ -0,0 +1,395 @@ +#requires -Version 3.0 + +<# + .SYNOPSIS + Remove the access to Outlook for all Mailboxes in an Microsoft Office 365 Tenant + + .DESCRIPTION + Remove the access to Outlook for all Mailboxes in an Microsoft Office 365 Tenant + It will remove access to OWA (Outlook Web Application), Exchange Active Sync (EAS), Outlook App and Outlook (part of the Office Suite). + + .PARAMETER CredentialUser + The UPN of the admin user + + .PARAMETER CredentialFile + File where the credential will be stored + + Make sure that this is secured! + + .PARAMETER ProxyAccessType + Determines which mechanism is used to resolve the host name. The acceptable values for this parameter are: + - IEConfig + - WinHttpConfig + - AutoDetect + - NoProxyServer + - None + + The default value is None. + + For information about the values of this parameter, see the description of the System.Management.Automation.Remoting.ProxyAccessTypehttp://go.microsoft.com/fwlink/?LinkId=144756 (http://go.microsoft.com/fwlink/?LinkId=144756) enumeration in the Microsoft Developer Network (MSDN) library. + + .EXAMPLE + PS C:\> .\Approve-CASMailboxSettings.ps1 + + .EXAMPLE + PS C:\> .\Approve-CASMailboxSettings.ps1 -verbose + + .NOTES + I created the script to run automated (via Windows scheduler) and it will save the password in a plain text file. + You might want to use another option to gain access to Exchange Online + + Please check all values before using the script! + + TODO: Run the script once before using it as scheduled task! This will create and save the credentials. +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('Username', 'AdminUser')] + [string] + $CredentialUser = 'youradmin.user@contoso.com', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('CredFile', 'SecretFile')] + [string] + $CredentialFile = ($env:LOCALAPPDATA + '\exocreds.txt'), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateSet('IEConfig', 'WinHttpConfig', 'AutoDetect', 'NoProxyServer', 'None', IgnoreCase = $true)] + [ValidateNotNullOrEmpty()] + [Alias('PSSessionOptionProxy')] + [string] + $ProxyAccessType = 'None' +) + +begin +{ + # Admin User (Global Admin or min. Exchange Online Admin role) + if (-not ($CredentialUser)) + { + $CredentialUser = 'youradmin.user@contoso.com' + } + + # Where to store the password? + if (-not ($CredentialFile)) + { + $CredentialFile = ($env:LOCALAPPDATA + '\exocreds.txt') + } +} + +process +{ + #region CredentialHandler + try + { + if (-not (Test-Path -Path $CredentialFile -ErrorAction SilentlyContinue)) + { + # Do we have any credentials in memory (variable) + if (-not ($ExoCreds)) + { + # + $paramGetCredential = @{ + Message = 'Bitte mit einem Exchange Online Admin Benutzer anmelden' + UserName = $CredentialUser + ErrorAction = 'Stop' + } + $ExoCreds = (Get-Credential @paramGetCredential) + } + + # Splat the parameters + $paramOutFile = @{ + FilePath = $CredentialFile + Force = $true + Encoding = 'utf8' + ErrorAction = 'Stop' + Confirm = $false + } + + # Save the file + $null = ($ExoCreds.Password | ConvertFrom-SecureString | Out-File @paramOutFile) + } + else + { + # Splat the parameters + $paramGetContent = @{ + Path = $CredentialFile + Force = $true + ErrorAction = 'Stop' + } + $paramConvertToSecureString = @{ + ErrorAction = 'Stop' + } + + # Read and convert the file wit the password + $PwdSecureString = (Get-Content @paramGetContent | ConvertTo-SecureString @paramConvertToSecureString) + + # Splat the parameters + $paramNewObject = @{ + TypeName = 'System.Management.Automation.PSCredential' + ArgumentList = $CredentialUser, $PwdSecureString + } + + # Create the credential object + $ExoCreds = (New-Object @paramNewObject) + + # Remove the password string from memory + $PwdSecureString = $null + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + #endregion CredentialHandler + + #region ConnectExchangeOnline + try + { + # Proxy Handling + <# + -ProxyAccessType + Determines which mechanism is used to resolve the host name. The acceptable values for this parameter are: + - IEConfig + - WinHttpConfig + - AutoDetect + - NoProxyServer + - None + + The default value is None. + For information about the values of this parameter, see the description of the System.Management.Automation.Remoting.ProxyAccessTypehttp://go.microsoft.com/fwlink/?LinkId=144756 (http://go.microsoft.com/fwlink/?LinkId=144756) enumeration in the Microsoft Developer Network (MSDN) library. + + Source: + Get-Help New-PSSessionOption -Detailed + #> + if ($ProxyAccessType) + { + # Splat the parameters + $paramNewPSSessionOption = @{ + ProxyAccessType = $ProxyAccessType + ErrorAction = 'Stop' + } + + # Do we need a proxy to access Office 365? + $ProxyOptions = (New-PSSessionOption @paramNewPSSessionOption) + } + + # Cleanup + $ExoSession = $null + + # Splat the parameters + $paramGetPSSession = @{ + ErrorAction = 'SilentlyContinue' + } + $paramRemovePSSession = @{ + ErrorAction = 'SilentlyContinue' + Confirm = $false + } + + # Remove all existing Exchange Online Sessions + $null = (Get-PSSession @paramGetPSSession | Where-Object { + $_.ComputerName -eq 'outlook.office365.com' + } | Remove-PSSession @paramRemovePSSession) + + # Splat the parameters + $paramNewPSSession = @{ + ConfigurationName = 'Microsoft.Exchange' + ConnectionUri = 'https://outlook.office365.com/powershell-liveid/' + Credential = $ExoCreds + Authentication = 'Basic' + AllowRedirection = $true + ErrorAction = 'Stop' + } + + # Proxy settings needed? + if ($ProxyOptions) + { + $paramNewPSSession.SessionOption = $ProxyOptions + } + + # Create the session + $ExoSession = (New-PSSession @paramNewPSSession) + + # Splat the parameters + $paramImportPSSession = @{ + Session = $ExoSession + DisableNameChecking = $true + AllowClobber = $true + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + + # Create the Session + $null = (Import-PSSession @paramImportPSSession) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + #endregion ConnectExchangeOnline + + #region SetCASMailbox + try + { + # Check if the session is alive + if (-not (Get-Command -Name Get-CASMailbox)) + { + # Splat the parameters + $paramWriteError = @{ + Exception = 'Es scheint ein Problem mit der Exchange Online Verbindung zu geben!' + Message = 'Die erforderlichen Exchnage Online Befehle wurden nicht gefunden!' + Category = 'ResourceUnavailable' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Make sure we are done! + throw + } + + # Splat the parameters + $paramGetCASMailbox = @{ + ResultSize = 'unlimited' + Filter = { + (name -notlike 'DiscoverysearchMailbox*') + } + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $paramSetCASMailbox = @{ + ActiveSyncEnabled = $false + ImapEnabled = $false + MAPIEnabled = $false + OutlookMobileEnabled = $false + OWAEnabled = $false + OWAforDevicesEnabled = $false + PopEnabled = $false + SmtpClientAuthenticationDisabled = $false + UniversalOutlookEnabled = $false + Confirm = $false + ErrorAction = 'Continue' + WarningAction = 'Continue' + } + + # Remove the outlook access from all mailboxes + $null = (Get-CASMailbox @paramGetCASMailbox | Set-CASMailbox @paramSetCASMailbox) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + #endregion SetCASMailbox +} + +end +{ + # Cleanup + $ExoSession = $null + + # Splat the parameters + $paramGetPSSession = @{ + ErrorAction = 'SilentlyContinue' + } + $paramRemovePSSession = @{ + ErrorAction = 'SilentlyContinue' + Confirm = $false + } + + # Remove all existing Exchange Online Sessions + $null = (Get-PSSession @paramGetPSSession | Where-Object { + $_.ComputerName -eq 'outlook.office365.com' + } | Remove-PSSession @paramRemovePSSession) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ExchangeOnline/Export-DistributionGroup2Cloud.ps1 b/Powershell/PowerShell-collection/ExchangeOnline/Export-DistributionGroup2Cloud.ps1 new file mode 100644 index 0000000..44d44dc --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/Export-DistributionGroup2Cloud.ps1 @@ -0,0 +1,617 @@ +function Export-DistributionGroup2Cloud +{ + <# + .SYNOPSIS + Function to convert/migrate on-premises Exchange distribution group to a Cloud (Exchange Online) distribution group + + .DESCRIPTION + Copies attributes of a synchronized group to a placeholder group and CSV file. + After initial export of group attributes, the on-premises group can have the attribute "AdminDescription" set to "Group_NoSync" which will stop it from be synchronized. + The "-Finalize" switch can then be used to write the addresses to the new group and convert the name. The final group will be a cloud group with the same attributes as the previous but with the additional ability of being able to be "self-managed". + Once the contents of the new group are validated, the on-premises group can be deleted. + + .PARAMETER Group + Name of group to recreate. + + .PARAMETER CreatePlaceHolder + Create placeholder DistributionGroup wit ha given name. + + .PARAMETER Finalize + Convert a given placeholder group to final DistributionGroup. + + .PARAMETER ExportDirectory + Export Directory for internal CSV handling. + + .EXAMPLE + PS> Export-DistributionGroup2Cloud -Group "DL-Marketing" -CreatePlaceHolder + + Create the Placeholder for the distribution group "DL-Marketing" + + .EXAMPLE + PS> Export-DistributionGroup2Cloud -Group "DL-Marketing" -Finalize + + Transform the Placeholder for the distribution group "DL-Marketing" to the real distribution group in the cloud + + .NOTES + This function is based on the Recreate-DistributionGroup.ps1 script of Joe Palarchio + + License: BSD 3-Clause + + .LINK + https://gallery.technet.microsoft.com/PowerShell-Script-to-Move-5c3cd668 + + .LINK + http://blogs.perficient.com/microsoft/?p=32092 + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param + ( + [Parameter(Mandatory, + HelpMessage = 'Name of group to recreate.')] + [string] + $Group, + [switch] + $CreatePlaceHolder, + [switch] + $Finalize, + [ValidateNotNullOrEmpty()] + [string] + $ExportDirectory = 'C:\scripts\PowerShell\exports\ExportedAddresses\' + ) + + begin + { + # Defaults + $SCN = 'SilentlyContinue' + $CNT = 'Continue' + $STP = 'Stop' + } + + process + { + If ($CreatePlaceHolder.IsPresent) + { + # Create the Placeholder + If (((Get-DistributionGroup -Identity $Group -ErrorAction $SCN).IsValid) -eq $True) + { + # Splat to make it more human readable + $paramGetDistributionGroup = @{ + Identity = $Group + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $OldDG = (Get-DistributionGroup @paramGetDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + try + { + [IO.Path]::GetInvalidFileNameChars() | ForEach-Object -Process { + $Group = $Group.Replace($_, '_') + } + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + $OldName = [string]$OldDG.Name + $OldDisplayName = [string]$OldDG.DisplayName + $OldPrimarySmtpAddress = [string]$OldDG.PrimarySmtpAddress + $OldAlias = [string]$OldDG.Alias + + # Splat to make it more human readable + $paramGetDistributionGroupMember = @{ + Identity = $OldDG.Name + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $OldMembers = ((Get-DistributionGroupMember @paramGetDistributionGroupMember).Name) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + If (!(Test-Path -Path $ExportDirectory -ErrorAction $SCN -WarningAction $CNT)) + { + Write-Verbose -Message (' Creating Directory: {0}' -f $ExportDirectory) + + # Splat to make it more human readable + $paramNewItem = @{ + ItemType = 'directory' + Path = $ExportDirectory + Force = $True + Confirm = $False + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $null = (New-Item @paramNewItem) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + } + + # Define variables - mostly for future use + $ExportDirectoryGroupCsv = $ExportDirectory + '\' + $Group + '.csv' + + try + { + # TODO: Refactor in future version + 'EmailAddress' > $ExportDirectoryGroupCsv + $OldDG.EmailAddresses >> $ExportDirectoryGroupCsv + 'x500:' + $OldDG.LegacyExchangeDN >> $ExportDirectoryGroupCsv + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + # Define variables - mostly for future use + $NewDistributionGroupName = 'Cloud- ' + $OldName + $NewDistributionGroupAlias = 'Cloud-' + $OldAlias + $NewDistributionGroupDisplayName = 'Cloud-' + $OldDisplayName + $NewDistributionGroupPrimarySmtpAddress = 'Cloud-' + $OldPrimarySmtpAddress + + # TODO: Replace with Write-Verbose in future version of the function + Write-Output -InputObject (' Creating Group: {0}' -f $NewDistributionGroupDisplayName) + + # Splat to make it more human readable + $paramNewDistributionGroup = @{ + Name = $NewDistributionGroupName + Alias = $NewDistributionGroupAlias + DisplayName = $NewDistributionGroupDisplayName + ManagedBy = $OldDG.ManagedBy + Members = $OldMembers + PrimarySmtpAddress = $NewDistributionGroupPrimarySmtpAddress + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $null = (New-DistributionGroup @paramNewDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + # Wait for 3 seconds + $null = (Start-Sleep -Seconds 3) + + # Define variables - mostly for future use + $SetDistributionGroupIdentity = 'Cloud-' + $OldName + $SetDistributionGroupDisplayName = 'Cloud-' + $OldDisplayName + + # TODO: Replace with Write-Verbose in future version of the function + Write-Output -InputObject (' Setting Values For: {0}' -f $SetDistributionGroupDisplayName) + + # Splat to make it more human readable + $paramSetDistributionGroup = @{ + Identity = $SetDistributionGroupIdentity + AcceptMessagesOnlyFromSendersOrMembers = $OldDG.AcceptMessagesOnlyFromSendersOrMembers + RejectMessagesFromSendersOrMembers = $OldDG.RejectMessagesFromSendersOrMembers + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $null = (Set-DistributionGroup @paramSetDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + # Define variables - mostly for future use + $SetDistributionGroupIdentity = 'Cloud-' + $OldName + + # Splat to make it more human readable + $paramSetDistributionGroup = @{ + Identity = $SetDistributionGroupIdentity + AcceptMessagesOnlyFrom = $OldDG.AcceptMessagesOnlyFrom + AcceptMessagesOnlyFromDLMembers = $OldDG.AcceptMessagesOnlyFromDLMembers + BypassModerationFromSendersOrMembers = $OldDG.BypassModerationFromSendersOrMembers + BypassNestedModerationEnabled = $OldDG.BypassNestedModerationEnabled + CustomAttribute1 = $OldDG.CustomAttribute1 + CustomAttribute2 = $OldDG.CustomAttribute2 + CustomAttribute3 = $OldDG.CustomAttribute3 + CustomAttribute4 = $OldDG.CustomAttribute4 + CustomAttribute5 = $OldDG.CustomAttribute5 + CustomAttribute6 = $OldDG.CustomAttribute6 + CustomAttribute7 = $OldDG.CustomAttribute7 + CustomAttribute8 = $OldDG.CustomAttribute8 + CustomAttribute9 = $OldDG.CustomAttribute9 + CustomAttribute10 = $OldDG.CustomAttribute10 + CustomAttribute11 = $OldDG.CustomAttribute11 + CustomAttribute12 = $OldDG.CustomAttribute12 + CustomAttribute13 = $OldDG.CustomAttribute13 + CustomAttribute14 = $OldDG.CustomAttribute14 + CustomAttribute15 = $OldDG.CustomAttribute15 + ExtensionCustomAttribute1 = $OldDG.ExtensionCustomAttribute1 + ExtensionCustomAttribute2 = $OldDG.ExtensionCustomAttribute2 + ExtensionCustomAttribute3 = $OldDG.ExtensionCustomAttribute3 + ExtensionCustomAttribute4 = $OldDG.ExtensionCustomAttribute4 + ExtensionCustomAttribute5 = $OldDG.ExtensionCustomAttribute5 + GrantSendOnBehalfTo = $OldDG.GrantSendOnBehalfTo + HiddenFromAddressListsEnabled = $True + MailTip = $OldDG.MailTip + MailTipTranslations = $OldDG.MailTipTranslations + MemberDepartRestriction = $OldDG.MemberDepartRestriction + MemberJoinRestriction = $OldDG.MemberJoinRestriction + ModeratedBy = $OldDG.ModeratedBy + ModerationEnabled = $OldDG.ModerationEnabled + RejectMessagesFrom = $OldDG.RejectMessagesFrom + RejectMessagesFromDLMembers = $OldDG.RejectMessagesFromDLMembers + ReportToManagerEnabled = $OldDG.ReportToManagerEnabled + ReportToOriginatorEnabled = $OldDG.ReportToOriginatorEnabled + RequireSenderAuthenticationEnabled = $OldDG.RequireSenderAuthenticationEnabled + SendModerationNotifications = $OldDG.SendModerationNotifications + SendOofMessageToOriginatorEnabled = $OldDG.SendOofMessageToOriginatorEnabled + BypassSecurityGroupManagerCheck = $True + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $null = (Set-DistributionGroup @paramSetDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + } + Else + { + Write-Error -Message ('The distribution group {0} was not found' -f $Group) -ErrorAction $CNT + } + } + ElseIf ($Finalize.IsPresent) + { + # Do the final steps + + # Define variables - mostly for future use + $GetDistributionGroupIdentity = 'Cloud-' + $Group + + # Splat to make it more human readable + $paramGetDistributionGroup = @{ + Identity = $GetDistributionGroupIdentity + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $TempDG = (Get-DistributionGroup @paramGetDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + $TempPrimarySmtpAddress = $TempDG.PrimarySmtpAddress + + try + { + [IO.Path]::GetInvalidFileNameChars() | ForEach-Object -Process { + $Group = $Group.Replace($_, '_') + } + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + $OldAddressesPatch = $ExportDirectory + '\' + $Group + '.csv' + + # Splat to make it more human readable + $paramImportCsv = @{ + Path = $OldAddressesPatch + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $OldAddresses = @(Import-Csv @paramImportCsv) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + try + { + $NewAddresses = $OldAddresses | ForEach-Object -Process { + $_.EmailAddress.Replace('X500', 'x500') + } + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + $NewDGName = $TempDG.Name.Replace('Cloud-', '') + $NewDGDisplayName = $TempDG.DisplayName.Replace('Cloud-', '') + $NewDGAlias = $TempDG.Alias.Replace('Cloud-', '') + + try + { + $NewPrimarySmtpAddress = ($NewAddresses | Where-Object -FilterScript { + $_ -clike 'SMTP:*' + }).Replace('SMTP:', '') + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + # Splat to make it more human readable + $paramSetDistributionGroup = @{ + Identity = $TempDG.Name + Name = $NewDGName + Alias = $NewDGAlias + DisplayName = $NewDGDisplayName + PrimarySmtpAddress = $NewPrimarySmtpAddress + HiddenFromAddressListsEnabled = $False + BypassSecurityGroupManagerCheck = $True + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $null = (Set-DistributionGroup @paramSetDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + $paramSetDistributionGroup = @{ + Identity = $NewDGName + EmailAddresses = @{ + Add = $NewAddresses + } + BypassSecurityGroupManagerCheck = $True + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $null = (Set-DistributionGroup @paramSetDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + + # Splat to make it more human readable + $paramSetDistributionGroup = @{ + Identity = $NewDGName + EmailAddresses = @{ + Remove = $TempPrimarySmtpAddress + } + BypassSecurityGroupManagerCheck = $True + ErrorAction = $STP + WarningAction = $CNT + } + try + { + $null = (Set-DistributionGroup @paramSetDistributionGroup) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + } + Else + { + Write-Error -Message " ERROR: No options selected, please use '-CreatePlaceHolder' or '-Finalize'" -ErrorAction $STP + + # Something that should never be reached + break + } + } + + end + { + <# + From the original Script Author + + Name: Recreate-DistributionGroup.ps1 + + Version: 1.0 + + Description: Copies attributes of a synchronized group to a placeholder group and CSV file. + After initial export of group attributes, the on-premises group can have the attribute "AdminDescription" set to "Group_NoSync" which will stop it from be synchronized. + The "-Finalize" switch can then be used to write the addresses to the new group and convert the name. The final group will be a cloud group with the same attributes as the previous but with the additional ability of being able to be "self-managed". + Once the contents of the new group are validated, the on-premises group can be deleted. + + Requires: Remote PowerShell Connection to Exchange Online + + Author: Joe Palarchio + + Usage: Additional information on the usage of this script can found at the following blog post: http://blogs.perficient.com/microsoft/?p=32092 + + Disclaimer: This script is provided AS IS without any support. Please test in a lab environment prior to production use. + #> + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ExchangeOnline/Get-MobileDeviceReporting.ps1 b/Powershell/PowerShell-collection/ExchangeOnline/Get-MobileDeviceReporting.ps1 new file mode 100644 index 0000000..55a0ee9 --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/Get-MobileDeviceReporting.ps1 @@ -0,0 +1,275 @@ +#requires -Version 3.0 -Modules ExchangeOnlineManagement +<# + .SYNOPSIS + Get a basic report of Mobile Devices + + .DESCRIPTION + Get a basic report of Mobile Devices connected to the Microsoft 365 Tenant + + .EXAMPLE + PS C:\> .\Get-MobileDeviceReporting.ps1 + + .LINK + Connect-ExchangeOnline + + .LINK + Get-MobileDevice + + .LINK + Get-MobileDeviceStatistics + + .NOTES + Nothing fancy! Only a basic report as CSV +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + # Cleanup + $Stats = $null + $DeviceStats = $null + $Report = $null + $MobileDeviceList = $null + + # Garbage Collection + [GC]::Collect() + + try + { + $paramConnectExchangeOnline = @{ + ShowBanner = $true + BypassMailboxAnchoring = $true + ExchangeEnvironmentName = 'O365Default' + ErrorAction = 'SilentlyContinue' + } + $null = (Connect-ExchangeOnline @paramConnectExchangeOnline) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + + # Create new object + $Report = @() +} + + +process +{ + # Get all mobile devices in the Microsoft 365 tenant + <# + Option: -ActiveSync + Description: The ActiveSync switch filters the results by Exchange ActiveSync devices. + Source: https://docs.microsoft.com/en-us/powershell/module/exchange/get-mobiledevice?view=exchange-ps + #> + try + { + $paramGetMobileDevice = @{ + ResultSize = 'unlimited' + ErrorAction = 'Stop' + } + $MobileDeviceList = (Get-MobileDevice @paramGetMobileDevice) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + + # Loop over the List + foreach ($Device in $MobileDeviceList) + { + $Stats = $null + $DeviceStats = $null + + try + { + $paramGetMobileDeviceStatistics = @{ + Identity = $Device.Guid.toString() + ErrorAction = 'Stop' + } + $Stats = (Get-MobileDeviceStatistics @paramGetMobileDeviceStatistics) + + $DeviceStats = [PSCustomObject]@{ + Identity = $Device.Identity -replace '\\.+' + DeviceType = $Device.DeviceType + DeviceOS = $Device.DeviceOS + DeviceUserAgent = $Stats.DeviceUserAgent + DeviceModel = $Stats.DeviceModel + ClientType = $Stats.ClientType + FirstSyncTime = $Stats.FirstSyncTime + LastSuccessSync = $Stats.LastSuccessSync + LastSyncAttemptTime = $Stats.LastSyncAttemptTime + LastPolicyUpdateTime = $Stats.LastPolicyUpdateTime + LastPingHeartbeat = $Stats.LastPingHeartbeat + } + + $Report += $DeviceStats + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception + #endregion ErrorHandler + } + } + + # Create a Timestamp (check if this is OK for you) + $TimeStamp = (Get-Date -Format yyyyMMdd_HHmmss) + + # Export the CSV Report + try + { + $paramExportCsv = @{ + Path = ('.\MobileDeviceReport' + $TimeStamp + '.csv') + Force = $true + Encoding = 'UTF8' + Delimiter = ';' + NoTypeInformation = $true + ErrorAction = 'Stop' + } + ($Report | Export-Csv @paramExportCsv) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + #endregion ErrorHandler + } + finally + { + # Disconnect from Exchange Online + $paramDisconnectExchangeOnline = @{ + Confirm = $false + ErrorAction = 'SilentlyContinue' + } + $null = (Disconnect-ExchangeOnline @paramDisconnectExchangeOnline) + + # Cleanup + $Stats = $null + $DeviceStats = $null + $Report = $null + $MobileDeviceList = $null + + # Garbage Collection + [GC]::Collect() + } +} + +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxFolderPermissionReport.ps1 b/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxFolderPermissionReport.ps1 new file mode 100644 index 0000000..54efc2a --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxFolderPermissionReport.ps1 @@ -0,0 +1,393 @@ +function Get-enMailboxFolderPermissionReport +{ + <# + .SYNOPSIS + Get a detailed mailbox folder permission report + + .DESCRIPTION + Get a detailed mailbox folder permission report and exports this report to a given CSV file. + You can select only user-mailboxes, only shared-mailboxes or both for the reporting. + + .PARAMETER Identity + The Identity parameter specifies the mailbox that you want to view. + You can use any value that uniquely identifies the mailbox. + + Default is * (all) + + .PARAMETER MailboxType + The type is the value for the regular RecipientTypeDetails. + + The acceptable values for this parameter are: + - UserMailbox + - User + - SharedMailbox + - Shared + - All + + The Default is ALL + + .PARAMETER ResultSize + The ResultSize parameter specifies the maximum number of results to return. + If you want to return all requests that match the query, use unlimited for the value of this parameter. + + The default value is unlimited. + + .PARAMETER Path + Specifies the path to the CSV output file. + + The default is 'C:\scripts\PowerShell\Reports\MailboxFolderPermissionReport.csv' + + .PARAMETER Encoding + Specifies the encoding for the exported CSV file. + The acceptable values for this parameter are: + - Unicode + - UTF7 + - UTF8 + - ASCII + - UTF32 + - BigEndianUnicode + - Default + - OEM + + Default is UTF8 + + .EXAMPLE + PS C:\> Get-enMailboxFolderPermissionReport + + Get a detailed mailbox folder permission report + + .NOTES + Developed and tested with Exchange Online, it should work with on Premises Exchange 2010/2010/2016/2019 + + This is open-source software, if you find an issue try to fix it yourself. + There is no support and/or warranty in any kind + + .LINK + http://www.enatec.io + + .LINK + Get-Mailbox + + .LINK + Get-MailboxFolderStatistics + + .LINK + Get-MailboxFolderPermission + + .LINK + Export-Csv + #> + + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyString()] + [AllowEmptyCollection()] + [Alias('Mailbox', 'MailboxID', 'MailboxIdentity')] + [string] + $Identity = '*', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateSet('UserMailbox', 'User', 'SharedMailbox', 'Shared', 'All', IgnoreCase = $true)] + [string] + $MailboxType = 'All', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('MailboxResultSize')] + [string] + $ResultSize = 'Unlimited', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('CsvReport', 'CsvFile')] + [string] + $Path = 'C:\scripts\PowerShell\Reports\MailboxFolderPermissionReport.csv', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateSet('Unicode', 'UTF7', 'UTF8', 'ASCII', 'UTF32', 'BigEndianUnicode', 'Default', 'OEM', IgnoreCase = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('CsvEncoding')] + [string] + $Encoding = 'UTF8' + ) + + begin + { + #region Cleanup + $MailboxPermissionReport = $null + $AllMailboxes = $null + $MailboxCount = $null + $MailboxFolderPermission = $null + $ProgressStatus = $null + #endregion Cleanup + + #region Defaults + $SCT = 'SilentlyContinue' + $CNT = 'Continue' + + if (-not ($Identity)) + { + $Identity = '*' + } + + if (-not ($MailboxType)) + { + $MailboxType = 'All' + } + + if (-not ($ResultSize)) + { + $ResultSize = 'Unlimited' + } + + if (-not ($Path)) + { + $Path = 'C:\scripts\PowerShell\Reports\MailboxFolderPermissionReport.csv' + } + + if (-not ($Encoding)) + { + $Encoding = 'UTF8' + } + #endregion Defaults + + #region MailboxType + Write-Verbose -Message 'Get the mailboxes' + + #region paramGetMailbox + $paramGetMailbox = @{ + Identity = $Identity + ResultSize = $ResultSize + ErrorAction = $SCT + WarningAction = $CNT + } + #endregion paramGetMailbox + + #region MailboxTypeSwitch + switch ($MailboxType) + { + UserMailbox + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' + } + } + } + User + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' + } + } + } + SharedMailbox + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + Shared + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + All + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' -or $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + default + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' -or $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + } + #endregion MailboxTypeSwitch + + #region GetAllMailboxes + $AllMailboxes = (Get-Mailbox @paramGetMailbox | Where-Object @paramWhereObject | Sort-Object) + #endregion GetAllMailboxes + #endregion MailboxType + } + + process + { + if ($AllMailboxes) + { + # Create a new object for the report + $MailboxPermissionReport = @() + + # Create a counter for Write-Progress + $MailboxCounter = ($AllMailboxes | Measure-Object).Count + + # Set the start counter for Write-Progress to 1 + $MailboxCount = 1 + + #region MailboxLoop + Write-Verbose -Message 'Process all mailboxes' + + ForEach ($SingleMailbox in $AllMailboxes) + { + # Update Write-Progress + $ProgressActivity = ('Working on Mailbox {0} of {1} ({2})' -f $MailboxCount, $MailboxCounter, $SingleMailbox.UserPrincipalName) + $ProgressStatus = ('Getting folders for mailbox: {0} ({1})' -f $SingleMailbox.DisplayName, $SingleMailbox.UserPrincipalName) + + Write-Verbose -Message $ProgressStatus + + $paramWriteProgress = @{ + Status = $ProgressStatus + Activity = $ProgressActivity + PercentComplete = (($MailboxCount/$MailboxCounter) * 100) + } + Write-Progress @paramWriteProgress + + # Get all folder for the mailbox + $AllFolders = ($SingleMailbox | Get-MailboxFolderStatistics -FolderScope All | ForEach-Object -Process { + $_.folderpath + } | ForEach-Object -Process { + $_.replace('/', '\') + }) + + ForEach ($SingleFolder in $AllFolders) + { + # Update Write-Progress + $ProgressStatus = ('Get permissions for {0}' -f ($SingleMailbox.UserPrincipalName + ':' + $SingleFolder)) + + Write-Verbose -Message $ProgressStatus + + $paramWriteProgress = @{ + Status = $ProgressStatus + Activity = $ProgressActivity + PercentComplete = (($MailboxCount/$MailboxCounter) * 100) + } + Write-Progress @paramWriteProgress + + # Get mailbox folder permissions with Get-MailboxFolderPermission + $MailboxFolderPermission = $null + $paramGetMailboxFolderPermission = @{ + Identity = ($SingleMailbox.Alias + ':' + $SingleFolder) + ErrorAction = $SCT + } + $MailboxFolderPermission = (Get-MailboxFolderPermission @paramGetMailboxFolderPermission) + + # store results in variable + $MailboxPermissionReport += $MailboxFolderPermission | Where-Object -FilterScript { + $_.User -notlike 'Default' -and $_.User -notlike 'Anonymous' -and $_.AccessRights -notlike 'None' -and $_.AccessRights -notlike 'Owner' + } | Select-Object -Property @{ + name = 'Name' + expression = { + $SingleMailbox.Name + } + }, @{ + name = 'UserPrincipalName' + expression = { + $SingleMailbox.UserPrincipalName + } + }, FolderName, @{ + name = 'User' + expression = { + $_.User -join ',' + } + }, @{ + name = 'AccessRights' + expression = { + $_.AccessRights -join ',' + } + } + + # Cleanup + $MailboxFolderPermission = $null + } + + # Update the counter + $MailboxCount++ + + Write-Verbose -Message ('Done with processing {0}' -f $SingleMailbox.UserPrincipalName) + } + #endregion MailboxLoop + + #region Reporter + if ($MailboxPermissionReport) + { + $paramExportCsv = @{ + Path = $Path + Force = $true + NoTypeInformation = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = $CNT + } + $null = ($MailboxPermissionReport | Export-Csv @paramExportCsv) + } + else + { + Write-Warning -Message 'None of the Mailboxes has special permissions set' + } + #endregion Reporter + } + else + { + Write-Warning -Message 'No Mailboxes found that matches your search criteria' + } + } + + end + { + #region Cleanup + $MailboxPermissionReport = $null + $AllMailboxes = $null + $MailboxCount = $null + $MailboxFolderPermission = $null + $ProgressStatus = $null + #endregion Cleanup + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxPermissionReport.ps1 b/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxPermissionReport.ps1 new file mode 100644 index 0000000..ed8bacd --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxPermissionReport.ps1 @@ -0,0 +1,335 @@ +function Get-enMailboxPermissionReport +{ + <# + .SYNOPSIS + Get a detailed mailbox permission report + + .DESCRIPTION + Get a detailed mailbox permission report and exports this report to a given CSV file. + You can select only user-mailboxes, only shared-mailboxes or both for the reporting. + + .PARAMETER Identity + The Identity parameter specifies the mailbox that you want to view. + You can use any value that uniquely identifies the mailbox. + + Default is * (all) + + .PARAMETER MailboxType + The type is the value for the regular RecipientTypeDetails. + + The acceptable values for this parameter are: + - UserMailbox + - User + - SharedMailbox + - Shared + - All + + The Default is ALL + + .PARAMETER ResultSize + The ResultSize parameter specifies the maximum number of results to return. + If you want to return all requests that match the query, use unlimited for the value of this parameter. + + The default value is unlimited. + + .PARAMETER Path + Specifies the path to the CSV output file. + + The default is 'C:\scripts\PowerShell\Reports\MailboxPermissionReport.csv' + + .PARAMETER Encoding + Specifies the encoding for the exported CSV file. + The acceptable values for this parameter are: + - Unicode + - UTF7 + - UTF8 + - ASCII + - UTF32 + - BigEndianUnicode + - Default + - OEM + + Default is UTF8 + + .EXAMPLE + PS C:\> Get-enMailboxPermissionReport + + Get a detailed mailbox permission report + + .NOTES + Developed and tested with Exchange Online, it should work with on Premises Exchange 2010/2010/2016/2019 + + This is open-source software, if you find an issue try to fix it yourself. + There is no support and/or warranty in any kind + + .LINK + http://www.enatec.io + + .LINK + Get-Mailbox + + .LINK + Get-RecipientPermission + + .LINK + Export-Csv + #> + + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyString()] + [AllowEmptyCollection()] + [Alias('Mailbox', 'MailboxID', 'MailboxIdentity')] + [string] + $Identity = '*', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateSet('UserMailbox', 'User', 'SharedMailbox', 'Shared', 'All', IgnoreCase = $true)] + [string] + $MailboxType = 'All', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('MailboxResultSize')] + [string] + $ResultSize = 'Unlimited', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('CsvReport', 'CsvFile')] + [string] + $Path = 'C:\scripts\PowerShell\Reports\MailboxPermissionReport.csv', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateSet('Unicode', 'UTF7', 'UTF8', 'ASCII', 'UTF32', 'BigEndianUnicode', 'Default', 'OEM', IgnoreCase = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('CsvEncoding')] + [string] + $Encoding = 'UTF8' + ) + + begin + { + #region Cleanup + $MailboxPermissionReport = $null + $AllMailboxes = $null + #endregion Cleanup + + #region Defaults + $SCT = 'SilentlyContinue' + $CNT = 'Continue' + + if (-not ($Identity)) + { + $Identity = '*' + } + + if (-not ($MailboxType)) + { + $MailboxType = 'All' + } + + if (-not ($ResultSize)) + { + $ResultSize = 'Unlimited' + } + + if (-not ($Path)) + { + $Path = 'C:\scripts\PowerShell\Reports\MailboxPermissionReport.csv' + } + + if (-not ($Encoding)) + { + $Encoding = 'UTF8' + } + #endregion Defaults + + #region MailboxType + Write-Verbose -Message 'Get the mailboxes' + + #region paramGetMailbox + $paramGetMailbox = @{ + Identity = $Identity + ResultSize = $ResultSize + ErrorAction = $SCT + WarningAction = $CNT + } + #endregion paramGetMailbox + + #region MailboxTypeSwitch + switch ($MailboxType) + { + UserMailbox + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' + } + } + } + User + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' + } + } + } + SharedMailbox + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + Shared + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + All + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' -or $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + default + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' -or $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + } + #endregion MailboxTypeSwitch + + #region GetAllMailboxes + $AllMailboxes = (Get-Mailbox @paramGetMailbox | Where-Object @paramWhereObject | Sort-Object) + #endregion GetAllMailboxes + #endregion MailboxType + } + + process + { + if ($AllMailboxes) + { + # Create a new object for the report + $MailboxPermissionReport = @() + + # Create a counter for Write-Progress + $MailboxCounter = ($AllMailboxes | Measure-Object).Count + + # Set the start counter for Write-Progress to 1 + $MailboxCount = 1 + + #region MailboxLoop + Write-Verbose -Message 'Process all mailboxes' + + ForEach ($SingleMailbox in $AllMailboxes) + { + # Update Write-Progress + $ProgressActivity = ('Working on Mailbox {0} of {1} ({2})' -f $MailboxCount, $MailboxCounter, $SingleMailbox.UserPrincipalName) + $ProgressStatus = ('Getting folders for mailbox: {0} ({1})' -f $SingleMailbox.DisplayName, $SingleMailbox.UserPrincipalName) + + Write-Verbose -Message $ProgressStatus + + $paramWriteProgress = @{ + Status = $ProgressStatus + Activity = $ProgressActivity + PercentComplete = (($MailboxCount/$MailboxCounter) * 100) + } + Write-Progress @paramWriteProgress + + $MailboxPermissionReport += $SingleMailbox | Get-MailboxPermission | Where-Object -FilterScript { + ($_.IsInherited -eq $false) -and -not ($_.User -match 'NT AUTHORITY') + } | Select-Object -Property 'Identity', @{ + Name = 'UserPrincipalName' + Expression = { + $SingleMailbox.UserPrincipalName + } + }, 'User', @{ + Name = 'Access Rights' + Expression = { + $_.AccessRights -join ',' + } + } -ErrorAction $CNT -WarningAction $CNT + } + #endregion MailboxLoop + + #region Reporter + if ($MailboxPermissionReport) + { + $paramExportCsv = @{ + Path = $Path + Force = $true + NoTypeInformation = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = $CNT + } + $null = ($MailboxPermissionReport | Export-Csv @paramExportCsv) + } + else + { + Write-Warning -Message 'None of the Mailboxes has special permissions set' + } + #endregion Reporter + } + else + { + Write-Warning -Message 'No Mailboxes found that matches your search criteria' + } + } + + end + { + #region Cleanup + $MailboxPermissionReport = $null + $AllMailboxes = $null + #endregion Cleanup + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxSendAsReport.ps1 b/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxSendAsReport.ps1 new file mode 100644 index 0000000..0b0744a --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/Get-enMailboxSendAsReport.ps1 @@ -0,0 +1,335 @@ +function Get-enMailboxSendAsReport +{ + <# + .SYNOPSIS + Get a detailed mailbox Send permission report + + .DESCRIPTION + Get a detailed mailbox Send permission report and exports this report to a given CSV file. + You can select only user-mailboxes, only shared-mailboxes or both for the reporting. + + .PARAMETER Identity + The Identity parameter specifies the mailbox that you want to view. + You can use any value that uniquely identifies the mailbox. + + Default is * (all) + + .PARAMETER MailboxType + The type is the value for the regular RecipientTypeDetails. + + The acceptable values for this parameter are: + - UserMailbox + - User + - SharedMailbox + - Shared + - All + + The Default is ALL + + .PARAMETER ResultSize + The ResultSize parameter specifies the maximum number of results to return. + If you want to return all requests that match the query, use unlimited for the value of this parameter. + + The default value is unlimited. + + .PARAMETER Path + Specifies the path to the CSV output file. + + The default is 'C:\scripts\PowerShell\Reports\MailboxSendAsReport.csv' + + .PARAMETER Encoding + Specifies the encoding for the exported CSV file. + The acceptable values for this parameter are: + - Unicode + - UTF7 + - UTF8 + - ASCII + - UTF32 + - BigEndianUnicode + - Default + - OEM + + Default is UTF8 + + .EXAMPLE + PS C:\> Get-enMailboxSendAsReport + + Get a detailed mailbox permission report + + .NOTES + Developed and tested with Exchange Online, it should work with on Premises Exchange 2010/2010/2016/2019 + + This is open-source software, if you find an issue try to fix it yourself. + There is no support and/or warranty in any kind + + .LINK + http://www.enatec.io + + .LINK + Get-Mailbox + + .LINK + Get-RecipientPermission + + .LINK + Export-Csv + #> + + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyString()] + [AllowEmptyCollection()] + [Alias('Mailbox', 'MailboxID', 'MailboxIdentity')] + [string] + $Identity = '*', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateSet('UserMailbox', 'User', 'SharedMailbox', 'Shared', 'All', IgnoreCase = $true)] + [string] + $MailboxType = 'All', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('MailboxResultSize')] + [string] + $ResultSize = 'Unlimited', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('CsvReport', 'CsvFile')] + [string] + $Path = 'C:\scripts\PowerShell\Reports\MailboxSendAsReport.csv', + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateSet('Unicode', 'UTF7', 'UTF8', 'ASCII', 'UTF32', 'BigEndianUnicode', 'Default', 'OEM', IgnoreCase = $true)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [Alias('CsvEncoding')] + [string] + $Encoding = 'UTF8' + ) + + begin + { + #region Cleanup + $MailboxPermissionReport = $null + $AllMailboxes = $null + #endregion Cleanup + + #region Defaults + $SCT = 'SilentlyContinue' + $CNT = 'Continue' + + if (-not ($Identity)) + { + $Identity = '*' + } + + if (-not ($MailboxType)) + { + $MailboxType = 'All' + } + + if (-not ($ResultSize)) + { + $ResultSize = 'Unlimited' + } + + if (-not ($Path)) + { + $Path = 'C:\scripts\PowerShell\Reports\MailboxSendAsReport.csv' + } + + if (-not ($Encoding)) + { + $Encoding = 'UTF8' + } + #endregion Defaults + + #region MailboxType + Write-Verbose -Message 'Get the mailboxes' + + #region paramGetMailbox + $paramGetMailbox = @{ + Identity = $Identity + ResultSize = $ResultSize + ErrorAction = $SCT + WarningAction = $CNT + } + #endregion paramGetMailbox + + #region MailboxTypeSwitch + switch ($MailboxType) + { + UserMailbox + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' + } + } + } + User + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' + } + } + } + SharedMailbox + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + Shared + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + All + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' -or $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + default + { + $paramWhereObject = @{ + FilterScript = { + $_.RecipientTypeDetails -eq 'UserMailbox' -or $_.RecipientTypeDetails -eq 'SharedMailbox' + } + } + } + } + #endregion MailboxTypeSwitch + + #region GetAllMailboxes + $AllMailboxes = (Get-Mailbox @paramGetMailbox | Where-Object @paramWhereObject | Sort-Object) + #endregion GetAllMailboxes + #endregion MailboxType + } + + process + { + if ($AllMailboxes) + { + # Create a new object for the report + $MailboxPermissionReport = @() + + # Create a counter for Write-Progress + $MailboxCounter = ($AllMailboxes | Measure-Object).Count + + # Set the start counter for Write-Progress to 1 + $MailboxCount = 1 + + #region MailboxLoop + Write-Verbose -Message 'Process all mailboxes' + + ForEach ($SingleMailbox in $AllMailboxes) + { + # Update Write-Progress + $ProgressActivity = ('Working on Mailbox {0} of {1} ({2})' -f $MailboxCount, $MailboxCounter, $SingleMailbox.UserPrincipalName) + $ProgressStatus = ('Getting folders for mailbox: {0} ({1})' -f $SingleMailbox.DisplayName, $SingleMailbox.UserPrincipalName) + + Write-Verbose -Message $ProgressStatus + + $paramWriteProgress = @{ + Status = $ProgressStatus + Activity = $ProgressActivity + PercentComplete = (($MailboxCount/$MailboxCounter) * 100) + } + Write-Progress @paramWriteProgress + + $MailboxPermissionReport += $SingleMailbox | Get-RecipientPermission | Where-Object -FilterScript { + ($_.IsInherited -eq $false) -and -not ($_.Trustee -match 'NT AUTHORITY') + } | Select-Object -Property 'Identity', @{ + Name = 'UserPrincipalName' + Expression = { + $SingleMailbox.UserPrincipalName + } + }, 'Trustee', @{ + Name = 'Access Rights' + Expression = { + $_.AccessRights -join ',' + } + } -ErrorAction $CNT -WarningAction $CNT + } + #endregion MailboxLoop + + #region Reporter + if ($MailboxPermissionReport) + { + $paramExportCsv = @{ + Path = $Path + Force = $true + NoTypeInformation = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = $CNT + } + $null = ($MailboxPermissionReport | Export-Csv @paramExportCsv) + } + else + { + Write-Warning -Message 'None of the Mailboxes has special permissions set' + } + #endregion Reporter + } + else + { + Write-Warning -Message 'No Mailboxes found that matches your search criteria' + } + } + + end + { + #region Cleanup + $MailboxPermissionReport = $null + $AllMailboxes = $null + #endregion Cleanup + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/ExchangeOnline/LICENSE b/Powershell/PowerShell-collection/ExchangeOnline/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/ExchangeOnline/Search-MailboxItemDeletion.ps1 b/Powershell/PowerShell-collection/ExchangeOnline/Search-MailboxItemDeletion.ps1 new file mode 100644 index 0000000..171f7c1 --- /dev/null +++ b/Powershell/PowerShell-collection/ExchangeOnline/Search-MailboxItemDeletion.ps1 @@ -0,0 +1,370 @@ +function Search-MailboxItemDeletion +{ + <# + .SYNOPSIS + Search for deletions in mailboxes + + .DESCRIPTION + Search for deletions in mailboxes, single or all + + .PARAMETER Days + Day (period) to search, max. 90 (or 30, based on your O365/M365 license). + The default is 7 (for the last 7 days) + Minimum is 1, maximum is 90. This will be checked + + .PARAMETER Mailbox + Mailbox Address + e.g. info@contoso.com + + .PARAMETER All + Get all deletes, for all mailboxes + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -All + + Get all deletes, for all mailboxes + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -Days 2 | Where-Object -FilterScript { $_.Folder -ne 'Deleted Items' } + + Get all deletes of the last 2 days, for all mailboxes, but we exclude one Folder. + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -Days 7 | Where-Object -FilterScript { $_.Folder -ne 'Deleted Items' } + + Get all deletes of the last 7 days, for all mailboxes, but we exclude one Folder. + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -Days 30 | Where-Object -FilterScript { ($_.Folder -ne 'Drafts') -and ($_.Action -ne 'SoftDelete') } + + Get all deletes of the last 30 days, for all mailboxes, but we exclude one Folder and the 'SoftDelete' action + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -Days 21 -All + + Get all deletes for the last 21 days, for all mailboxes + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -All | Out-GridView + + Search for Deletions in all mailboxes and open the result in the GridView (e.g. for filtering) + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -Mailbox 'info@contoso.com' + + Search for Deletions in the mailbox 'info@contoso.com' + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -Mailbox 'info@contoso.com' | Select-Object -Property 'Timestamp', 'Action', 'Status' , 'User', 'Mailbox', 'Subject', 'Folder', 'Client', 'ClientIP' + + Search for Deletions in the mailbox 'info@contoso.com', and get a few more properties (e.g. Status, Client, and ClientIP). + Might be handy to see from where it was triggered and what client was used. + + .EXAMPLE + PS C:\> Search-MailboxItemDeletion -Mailbox 'info@contoso.com' | Export-CSV -NoTypeInformation -Path c:\scripts\PowerShell\exports\ExchangeOnlineMailboxDeletes.csv + + Search for Deletions in the mailbox 'info@contoso.com' and export the result into a CSV File (e.g. for a basic reporting or further investigation in Excel) + + .OUTPUTS + array + + .LINK + Search-UnifiedAuditLog + + .NOTES + For now, the following properties are supported: + Action string + AppId string + Client string + ClientIP string + External bool + ExternalAccess bool + Folder string + InternalLogonType int + InternetMessageId string + LogonType int + Mailbox string + MailboxGuid string + MessageId string + OrganizationId string + OrganizationName string + OriginatingServer string + SessionId string + Status string + Subject string + TimeStamp string + User string + + By default, the following properties are returned (all others can be selected): + TimeStamp string + Action string + User string + Mailbox string + Subject string + Folder string + + Requirements: + PowerShell or Windows PowerShell + Exchange Online connection (e.g. the installed Module and you need to be connected with a user that has rights to use Search-UnifiedAuditLog) + + A future version might support Wildcards in the Mailbox parameter and/or multi Mailbox searches. + Workaround: use Where-Object with a powerful FilterScript! + #> + [CmdletBinding(DefaultParameterSetName = 'All', + ConfirmImpact = 'None')] + [OutputType([array])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [ValidateNotNull()] + [int] + $Days = 7, + [Parameter(ParameterSetName = 'Single', HelpMessage = 'Mailbox Address e.g. info@contoso.com', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [ValidateNotNull()] + [Alias('MailboxName', 'MailboxAddress')] + [string] + $Mailbox, + [Parameter(ParameterSetName = 'All')] + [switch] + $All + ) + + begin + { + # Garbage Collection + [GC]::Collect() + + # Cleanup + $Records = $null + + # TimeSpan + $StartDate = (Get-Date).AddDays(-$Days) + + # Now + $EndDate = (Get-Date) + + #region HelperFunctions + function Get-StandardMembersFromPSObject + { + <# + .SYNOPSIS + Filter the given properties from a given Object + + .DESCRIPTION + Filter the given properties from a given Object + + .PARAMETER InputObject + The input object, must be a psobject. + + .PARAMETER Properties + The properties to select from the given input object. + Multiple values needs to separated by a comma. + + .EXAMPLE + Get-StandardMembersFromPSObject -InputObject Value -Properties Value + Describe what this call does + + .OUTPUTS + psobject + + .NOTES + Just an internal Helper function + + .LINK + https://learn-powershell.net/2013/08/03/quick-hits-set-the-default-property-display-in-powershell-on-custom-objects/ + .LINK + http://stackoverflow.com/questions/1369542/can-you-set-an-objects-defaultdisplaypropertyset-in-a-powershell-v2-script/1891215#1891215 + + .INPUTS + psobject, string + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'The input object, must be a psobject.')] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [psobject] + $InputObject, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [Alias('DefaultProperties')] + [string[]] + $Properties = $null + ) + + process + { + try + { + $defaultDisplayPropertySet = (New-Object -TypeName System.Management.Automation.PSPropertySet -ArgumentList ('DefaultDisplayPropertySet', [string[]]$Properties)) + $PSStandardMembers = ([Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)) + $InputObject | Add-Member -MemberType MemberSet -Name PSStandardMembers -Value $PSStandardMembers -Force + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + #endregion ErrorHandler + } + } + } + #endregion HelperFunctions + } + + process + { + # Get the UnifiedAuditLog Data, with the delete operations + $Records = (Search-UnifiedAuditLog -StartDate $StartDate -EndDate $EndDate -Operations 'HardDelete', 'SoftDelete') + + # Do we have a result + if ($Records) + { + Write-Verbose -Message ('Processing ' + $Records.Count + ' audit records...') + + # Create a new Object + $Report = [Collections.Generic.List[Object]]::new() + + foreach ($Rec in $Records) + { + $AuditData = (ConvertFrom-Json -InputObject $Rec.Auditdata) + + if ($AuditData.ResultStatus -eq 'PartiallySucceeded') + { + $MessageSubject = '# Not fully deleted by' + $AuditData.ClientInfoString + ' #' + } + else + { + $MessageSubject = ($AuditData.AffectedItems.Subject -split '\n')[0] + } + + $ReportLine = [PSCustomObject] @{ + TimeStamp = (Get-Date -Date ($AuditData.CreationTime) -Format g) + User = $AuditData.UserId + Action = $AuditData.Operation + Status = $AuditData.ResultStatus + Mailbox = $AuditData.MailboxOwnerUPN + MailboxGuid = $AuditData.MailboxGuid + Subject = $MessageSubject + MessageId = ($AuditData.AffectedItems.Id -split '\n')[0] + InternetMessageId = ($AuditData.AffectedItems.InternetMessageId -split '\n')[0] + Folder = $AuditData.Folder.Path.Split('\')[1] + Client = $AuditData.ClientInfoString + AppId = $AuditData.AppId + ClientIP = $AuditData.ClientIP + External = $AuditData.ExternalAccess + SessionId = $AuditData.SessionId + ExternalAccess = $AuditData.ExternalAccess + InternalLogonType = $AuditData.InternalLogonType + LogonType = $AuditData.LogonType + OrganizationName = $AuditData.OrganizationName + OrganizationId = $AuditData.OrganizationId + OriginatingServer = $AuditData.OriginatingServer + } + + # Define the default properties and support Select-Object + Get-StandardMembersFromPSObject -InputObject $ReportLine -Properties 'Timestamp', 'Action', 'User', 'Mailbox', 'Subject', 'Folder' + + # Add to the reporting + $Report.Add($ReportLine) + } + + $Records = $null + } + else + { + Write-Output -InputObject 'No deletion records found.' + break + } + + # Create a new array object + $Output = @() + + # Single or all ? + switch ($PsCmdlet.ParameterSetName) + { + 'Single' + { + $Output = ($Report | Where-Object -FilterScript { + # You might want to tweak the filter to support Wildcards or more the one mailbox + $_.Mailbox -eq $Mailbox + }) + } + 'All' + { + $Output = ($Report | Sort-Object -Property Mailbox) + } + } + + # Cleanup + $Report = $null + } + + end + { + # Just dump the result to the terminal + $Output + + # Cleanup + $Output = $null + + # Garbage Collection + [GC]::Collect() + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Clear-MicrosoftTeamsClientCache.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Clear-MicrosoftTeamsClientCache.ps1 new file mode 100644 index 0000000..a852737 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Clear-MicrosoftTeamsClientCache.ps1 @@ -0,0 +1,167 @@ +<# + .SYNOPSIS + Cleanup Microsoft Teams Client + + .DESCRIPTION + Cleanup Microsoft Teams Client by deleting several local cache files + + .EXAMPLE + PS C:\> .\Clear-MicrosoftTeamsClientCache.ps1 + + Cleanup Microsoft Teams Client by deleting several local cache files + + .EXAMPLE + PS C:\> .\Clear-MicrosoftTeamsClientCache.ps1 -Verbose + + Cleanup Microsoft Teams Client by deleting several local cache files, but be verbose while doing it + + .EXAMPLE + PS C:\> .\Clear-MicrosoftTeamsClientCache.ps1 -WhatIf + Cleanup Microsoft Teams Client by deleting several local cache files - Dry Run!!! + + .NOTES + Due to some issues, Windows is not supported at this time! +#> +[CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] +param () + +if ($IsMacOS -eq $true) +{ + $AppDataBasePath = '~/Library/Application Support/Microsoft/Teams/' +} +else +{ + Write-Warning -Message 'Due to some issues, Windows is not supported at this time!' + + exit 1 + + $AppDataBasePath = ($env:APPDATA + '\Microsoft\teams\') +} + +#region BoundParameters +if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) +{ + $VerboseValue = $true +} +else +{ + $VerboseValue = $false +} + +if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) +{ + $DebugValue = $true +} +else +{ + $DebugValue = $false +} + +if (($PSCmdlet.MyInvocation.BoundParameters['WhatIf']).IsPresent) +{ + $WhatIfValue = $true +} +else +{ + $WhatIfValue = $false +} +#endregion BoundParameters + +#region +$paramGetChildItem = @{ + Verbose = $VerboseValue + Debug = $DebugValue + Recurse = $true + ErrorAction = 'SilentlyContinue' +} + +$paramRemoveItem = @{ + Verbose = $VerboseValue + Debug = $DebugValue + WhatIf = $WhatIfValue + Confirm = $false + Force = $true + Recurse = $true + ErrorAction = 'SilentlyContinue' +} +#endregion + +#region +if ($PSCmdlet.ShouldProcess('Microsoft Teams Client', 'Hard Kill')) +{ + $null = (Get-Process -Name Teams -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue) + Start-Sleep -Seconds 2 +} +#endregion + +Get-ChildItem -Path ($AppDataBasePath + 'blob_storage') @paramGetChildItem -Verbose -Debug | ForEach-Object -Process { + Remove-Item -Path $_.FullName @paramRemoveItem -WhatIf +} + +Get-ChildItem -Path ($AppDataBasePath + 'databases') @paramGetChildItem | ForEach-Object -Process { + Remove-Item -Path $_.FullName @paramRemoveItem +} + +Get-ChildItem -Path ($AppDataBasePath + 'Cache') @paramGetChildItem | ForEach-Object -Process { + Remove-Item -Path $_.FullName @paramRemoveItem +} + +Get-ChildItem -Path ($AppDataBasePath + 'gpucache') @paramGetChildItem | ForEach-Object -Process { + Remove-Item -Path $_.FullName @paramRemoveItem +} + +Get-ChildItem -Path ($AppDataBasePath + 'IndexedDB') @paramGetChildItem | ForEach-Object -Process { + Remove-Item -Path $_.FullName -Confirm:$false -Force -Recurse -ErrorAction SilentlyContinue +} + +Get-ChildItem -Path ($AppDataBasePath + 'Local Storage') @paramGetChildItem | ForEach-Object -Process { + Remove-Item -Path $_.FullName @paramRemoveItem +} + +Get-ChildItem -Path ($AppDataBasePath + 'tmp') @paramGetChildItem | ForEach-Object -Process { + Remove-Item -Path $_.FullName @paramRemoveItem +} + +Get-ChildItem -Path $AppDataBasePath -Include 'old_logs_*.txt', 'logs.txt', 'in_progress_download_metadata_store' @paramGetChildItem | ForEach-Object -Process { + Remove-Item -Path $_.FullName @paramRemoveItem +} + +if (Test-Path -Path ($AppDataBasePath + 'installTime.txt')) +{ + $InstallDateInput = (Get-Content -Path ($AppDataBasePath + 'installTime.txt')) + $Culture = (New-Object -TypeName System.Globalization.CultureInfo -ArgumentList ('de-DE')) + $InstallDate = (Get-Date -Date $InstallDateInput -Format ($Culture.DateTimeFormat.ShortDatePattern)) + + Write-Output -InputObject ('Latest Version of Microsoft Teams from: {0}' -f $InstallDate) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Default_MicrosoftTeams_DesktopConfig.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Default_MicrosoftTeams_DesktopConfig.ps1 new file mode 100644 index 0000000..f062fa5 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Default_MicrosoftTeams_DesktopConfig.ps1 @@ -0,0 +1,535 @@ +<# + .SYNOPSIS + Microsoft Teams Client customization settings via PowerShell + + .DESCRIPTION + Microsoft Teams Client customization settings via PowerShell + + .EXAMPLE + PS C:\> .\Default_MicrosoftTeams_DesktopConfig.ps1 + + .EXAMPLE + PS C:\> .\Default_MicrosoftTeams_DesktopConfig.ps1 -verbose + + .NOTES + Refactored and extended version of Desktop-Config-Json.ps1 by eshlomo1 + + .LINK + https://github.com/eshlomo1/MS_Teams/blob/master/Desktop-Config-Json.ps1 + + .LINK + https://www.eshlomo.us/microsoft-teams-client-personalization-with-powershell/ +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + #region DefaultSettings + $AppPrefSetOpenAsHidden = $false + $AppPrefSetOpenAtLogin = $false + $AppPrefSetRegisterAsIMProvider = $true + $AppPrefSetRunningOnClose = $false + $NotificationWindowOnClose = $true + $OverrideOpenAsHiddenProperty = $true + $IsAppFirstRun = $false + $CurrentWebLanguage = 'en-us' + #endregion DefaultSettings + + #region Cleanup + $ChangedConfig = $null + $SourceConfigFile = $null + $Teams = $null + #endregion Cleanup + + #region SetConfigPath + if (($PSVersionTable.PSEdition -eq 'Core') + ($PSVersionTable.Platform -eq 'Unix') -and ($PSVersionTable.OS -like 'Darwin*')) + { + # OK, macOS is supported + $SourceConfigFile = ($Env:HOME + '/Library/Application Support/Microsoft/Teams/desktop-config.json') + } + elseif (($PSVersionTable.PSEdition -eq 'Core') + ($PSVersionTable.Platform -eq 'Unix') -and ($PSVersionTable.OS -like 'Linux*')) + { + # Sorry, Linux is not supported... + $paramWriteError = @{ + Message = 'Sorry, Linux is not supported...' + Exception = 'Sorry, Linux is not supported!' + Category = 'NotImplemented' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + exit 1 + } + else + { + # Windows? Really??? OK, sure this is supported + $SourceConfigFile = ($env:userprofile + '\AppData\Roaming\Microsoft\Teams\desktop-config.json') + } + #endregion SetConfigPath +} + +process +{ + if (Test-Path -Path $SourceConfigFile -ErrorAction SilentlyContinue -WarningAction Continue) + { + #region GetConfig + try + { + # Splat the parameters + $paramGetContent = @{ + Path = $SourceConfigFile + Force = $true + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $Teams = (Get-Content @paramGetContent | ConvertFrom-Json -ErrorAction Stop) + + # Cleanup + $paramGetContent = $null + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Stop -Exception $e.Exception -TargetObject $e.CategoryInfo.TargetName + + break + } + #endregion GetConfig + + #region + if ($Teams.appPreferenceSettings) + { + if ($Teams.appPreferenceSettings.openAsHidden) + { + if ($Teams.appPreferenceSettings.openAsHidden -ne $AppPrefSetOpenAsHidden) + { + Write-Verbose -Message 'Value of openAsHidden will be changed to the desired default' + + $Teams.appPreferenceSettings.openAsHidden = $AppPrefSetOpenAsHidden + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of openAsHidden was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of openAsHidden is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter openAsHidden will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'openAsHidden' + Value = $AppPrefSetOpenAsHidden + } + $null = ($Teams.appPreferenceSettings | Add-Member @paramAddMember) + + # Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter openAsHidden was created with the desired default value' + } + + if ($Teams.appPreferenceSettings.openAtLogin) + { + if ($Teams.appPreferenceSettings.openAtLogin -ne $AppPrefSetOpenAtLogin) + { + Write-Verbose -Message 'Value of openAtLogin will be changed to the desired default' + + $Teams.appPreferenceSettings.openAtLogin = $AppPrefSetOpenAtLogin + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of openAtLogin was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of openAtLogin is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter openAtLogin will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'openAtLogin' + Value = $AppPrefSetOpenAtLogin + } + $null = ($Teams.appPreferenceSettings | Add-Member @paramAddMember) + + # Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter openAtLogin was created with the desired default value' + } + + if (($PSVersionTable.PSEdition -eq 'Core') + ($PSVersionTable.Platform -eq 'Unix') -and ($PSVersionTable.OS -like 'Darwin*') ) + { + Write-Verbose -Message 'The setting registerAsIMProvider is not supported on macOS...' + } + else + { + if ($Teams.appPreferenceSettings.registerAsIMProvider) + { + if ($Teams.appPreferenceSettings.registerAsIMProvider -ne $AppPrefSetRegisterAsIMProvider) + { + Write-Verbose -Message 'Value of registerAsIMProvider will be changed to the desired default' + + $Teams.appPreferenceSettings.registerAsIMProvider = $AppPrefSetRegisterAsIMProvider + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of registerAsIMProvider was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of registerAsIMProvider is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter registerAsIMProvider will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'registerAsIMProvider' + Value = $AppPrefSetRegisterAsIMProvider + } + $null = ($Teams.appPreferenceSettings | Add-Member @paramAddMember) + + # Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter registerAsIMProvider was created with the desired default value' + } + } + + if ($Teams.appPreferenceSettings.runningOnClose) + { + if ($Teams.appPreferenceSettings.runningOnClose -ne $AppPrefSetRunningOnClose) + { + Write-Verbose -Message 'Value of runningOnClose will be changed to the desired default' + + $Teams.appPreferenceSettings.runningOnClose = $AppPrefSetRunningOnClose + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of runningOnClose was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of runningOnClose is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter runningOnClose will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'runningOnClose' + Value = $AppPrefSetRunningOnClose + } + $null = ($Teams.appPreferenceSettings | Add-Member @paramAddMember) + + # Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter runningOnClose was created with the desired default value' + } + } + + if ($Teams.notificationWindowOnClose) + { + if ($Teams.notificationWindowOnClose -ne $NotificationWindowOnClose) + { + Write-Verbose -Message 'Value of notificationWindowOnClose will be changed to the desired default' + + $Teams.notificationWindowOnClose = $NotificationWindowOnClose + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of notificationWindowOnClose was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of notificationWindowOnClose is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter currentWebLanguage will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'notificationWindowOnClose' + Value = $NotificationWindowOnClose + } + $null = ($Teams | Add-Member @paramAddMember) + + # Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter currentWebLanguage was created with the desired default value' + } + + if ($Teams.overrideOpenAsHiddenProperty) + { + if ($Teams.overrideOpenAsHiddenProperty -ne $OverrideOpenAsHiddenProperty) + { + Write-Verbose -Message 'Value of overrideOpenAsHiddenProperty will be changed to the desired default' + + $Teams.overrideOpenAsHiddenProperty = $OverrideOpenAsHiddenProperty + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of overrideOpenAsHiddenProperty was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of overrideOpenAsHiddenProperty is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter overrideOpenAsHiddenProperty will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'overrideOpenAsHiddenProperty' + Value = $OverrideOpenAsHiddenProperty + } + $null = ($Teams | Add-Member @paramAddMember) + + # Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter overrideOpenAsHiddenProperty was created with the desired default value' + } + + if ($Teams.isAppFirstRun) + { + if ($Teams.isAppFirstRun -ne $IsAppFirstRun) + { + Write-Verbose -Message 'Value of isAppFirstRun will be changed to the desired default' + + $Teams.isAppFirstRun = $IsAppFirstRun + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of isAppFirstRun was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of isAppFirstRun is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter isAppFirstRun will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'isAppFirstRun' + Value = $false + } + $null = ($Teams | Add-Member @paramAddMember) + + # Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter isAppFirstRun was created with the desired default value' + } + + if ($Teams.currentWebLanguage) + { + if ($Teams.currentWebLanguage -ne $CurrentWebLanguage) + { + Write-Verbose -Message 'Value of currentWebLanguage will be changed to the desired default' + + $Teams.currentWebLanguage = $CurrentWebLanguage + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'Value of currentWebLanguage was changed to the desired default' + } + else + { + Write-Verbose -Message 'Value of currentWebLanguage is unchanged' + } + } + else + { + Write-Verbose -Message 'The Parameter currentWebLanguage will be created with the desired default value' + + # Splat the parameters + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = 'currentWebLanguage' + Value = $CurrentWebLanguage + } + $null = ($Teams | Add-Member @paramAddMember) + + #Cleanup + $paramAddMember = $null + + # Set the change indicator + $ChangedConfig = $true + + Write-Verbose -Message 'The Parameter currentWebLanguage was created with the desired default value' + } + #endregion + + #region SaveNewConfig + if ($ChangedConfig) + { + Write-Verbose -Message 'Changed configuration will be saved' + + try + { + # Splat the parameters + $paramConvertToJson = @{ + Compress = $true + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + + $paramSetContent = @{ + Path = $SourceConfigFile + Force = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + + $null = ($Teams | ConvertTo-Json @paramConvertToJson | Set-Content @paramSetContent) + + # Cleanup + $paramConvertToJson = $null + $paramSetContent = $null + $Teams = $null + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Stop -Exception $e.Exception -TargetObject $e.CategoryInfo.TargetName + + break + } + + Write-Verbose -Message 'Changed configuration was saved' + } + else + { + Write-Verbose -Message 'No changes made to the configuration' + } + #endregion SaveNewConfig + } + else + { + Write-Warning -Message 'No Configuration File for Microsoft Teams was found.' + + exit 1 + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Get-AllExternalTeamsApps.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Get-AllExternalTeamsApps.ps1 new file mode 100644 index 0000000..b1589f8 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Get-AllExternalTeamsApps.ps1 @@ -0,0 +1,65 @@ +#requires -Version 2.0 -Modules MicrosoftTeams + +<# + .SYNOPSIS + Get a List of external Microsoft Teams Applications + + .DESCRIPTION + Get a List of external Microsoft Teams Applications for the tenant. + + .EXAMPLE + PS C:\> .\Get-AllExternalTeamsApps.ps1 + + Get a List of external Microsoft Teams Applications for the tenant. + + .EXAMPLE + PS C:\> .\Get-AllExternalTeamsApps.ps1 | Select-Object -Property DisplayName, DistributionMethod + + Get a List of external Microsoft Teams Applications for the tenant. + + .NOTES + You need to use the Microsoft Teams Cmdlets module + + If you don't have, install it from the gallery: + Install-Module -Name MicrosoftTeams +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +<# + Simple filter: External Apps will have the ExternalId field filled, + where store apps (from the Microsoft Teams App Store) not. +#> +Get-TeamsApp | Where-Object -FilterScript { + $_.ExternalId +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Get-TeamsAssignedNumbers.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Get-TeamsAssignedNumbers.ps1 new file mode 100644 index 0000000..055a782 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Get-TeamsAssignedNumbers.ps1 @@ -0,0 +1,717 @@ +#requires -Version 3.0 -Modules MicrosoftTeams +<# + .SYNOPSIS + Collects assigned phone numbers from Microsoft Teams + + .DESCRIPTION + This script queries Microsoft Teams for assigned numbers and displays in a formatted table with the option to export the report in several formats + During processing LineURI's are run against a regex pattern to extract the DDI/DID and the extension to a separate column + + This script collects Microsoft Teams objects including: + Users, Meeting Rooms, Online Application Instances (Resource Accounts) + + .PARAMETER OutputType + Define the Script Output + + Valid values are: + CONSOLE - Dump a formatted list into the console + HTML - Create a simple HTML report with Tables. Only here to be compatible to our older version + XML - Create a simple Extensible Markup Language (XML) report + YAML - Create a simple YAML Ain't Markup Language (YAML) report + JSON - Create a simple JavaScript Object Notation (JSON) report. Handy if you need to upload the data via WebServices/APIs + CSV - Create a simple comma-separated values (CSV) report. This is perfect for re-use within Excel, or other applications + + If you leave it empty (this is the default), the object will be dumped to the console! + This can become handy, if you use this script to generate the report and re-use it in the pipe or your own application + + .PARAMETER Path + Where to store the Report File + + Default is 'C:\scripts\PowerShell\logs\' + + .PARAMETER DateFormat + Use the format for Get-Date + + Default is 'yyyyMMdd-HHmmUTC' + + .PARAMETER UTC + Use ToUniversalTime for the Date Strings + + Default is $true + + .PARAMETER Report + Define what to report. + + Valid values are: + Users - Report numbers assigned to users + MeetingRooms - Report numbers assigned to Meetings Room accounts + ResourceAccounts - Report numbers assigned to Applications. (Auto Attendants (AA) and/or Call Queues (CQ) are supported) + All - All assigned numbers (all above merged into one report) + + Default is 'All' + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 + + The Report will be dumped to the console (unformatted) + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType CONSOLE -Report MeetingRooms + + Dump a formatted report for numbers assigned to Meeting Rooms into the console + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType CONSOLE -Report ResourceAccounts + + Dump a formatted report for numbers assigned to Resource Accounts into the console + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType CONSOLE -Report Users + + Dump a formatted report for numbers assigned to Resource Accounts into the console + This will contain function users for Resource Accounts and Meeting Rooms, but they will be shown as user object! + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType CONSOLE -Report all + + Dump a formatted report for every assigned number into the console + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType HTML + + Create a simple HTML report with Tables. + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType XML + + Create a simple Extensible Markup Language (XML) report + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType YAML + + Create a simple YAML Ain't Markup Language (YAML) report + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType JSON + + Create a simple JavaScript Object Notation (JSON) report. + + .EXAMPLE + PS C:\> .\Get-TeamsAssignedNumbers.ps1 -OutputType CSV + + Create a simple comma-separated values (CSV) report. + + .LINK + https://github.com/ucgeek/Get-TeamsAssignedNumbers + + .LINK + https://github.com/ucgeek/Get-TeamsAssignedNumbers/blob/master/LICENSE + + .NOTES + Based on the work off Andrew Morpeth (@ucgeek and https://ucgeek.co/) + Licensed under the GNU General Public License v3.0 terms (by @ucgeek) + + REQUIREMENTS: + If you haven't already, you will need to install the MicrosoftTeams PowerShell module + The script assumes, you are connect to the Teams/Skype for Business Online Service of Microsoft Office 365 +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowNull()] + [AllowEmptyString()] + [AllowEmptyCollection()] + [ValidateSet('CONSOLE', 'HTML', 'XML', 'YAML', 'JSON', 'CSV', IgnoreCase = $true)] + [Alias('ReportFormat')] + [string] + $OutputType = $null, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowNull()] + [AllowEmptyString()] + [AllowEmptyCollection()] + [string] + $Path = 'C:\scripts\PowerShell\logs', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowNull()] + [AllowEmptyString()] + [AllowEmptyCollection()] + [string] + $DateFormat = 'yyyyMMdd-HHmmUTC', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('UseUTC')] + [switch] + $UTC, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [AllowNull()] + [ValidateSet('Users', 'MeetingRooms', 'ResourceAccounts', 'All', IgnoreCase = $true)] + [Alias('ReportType')] + [string[]] + $Report = 'All' +) + +begin +{ + #region BoundParameters + if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + { + $VerboseValue = $true + } + else + { + $VerboseValue = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) + { + $DebugValue = $true + } + else + { + $DebugValue = $false + } + #endregion BoundParameters + + #region DateToUTC + if (-not ($UTC)) + { + $UTC = $true + } + #endregion DateToUTC + + #region UseDateUTC + if (($UTC -eq $true) -and ($DateFormat)) + { + $FileName = ('MicrosoftTeamsAssignedNumbers_' + ((Get-Date).ToUniversalTime()).ToString($DateFormat)) + } + #endregion UseDateUTC + + #region UseDateFormat + if ($DateFormat) + { + $FileName = ('MicrosoftTeamsAssignedNumbers_' + ((Get-Date).ToString($DateFormat))) + } + else + { + # This is the default + $FileName = ('MicrosoftTeamsAssignedNumbers_' + (Get-Date -Format s).replace(':', '-')) + } + #endregion UseDateFormat + + #region PathMangle + if ($Path) + { + # Save to a given PATH + $FilePath = ($Path + '\' + $FileName) + } + else + { + # Save here (where the script was started) + $FilePath = ('.\' + $FileName) + } + #endregion PathMangle + + #region Regex + # Regex values + $LineURIRegex = '^(?:tel:)?(?:\+)?(\d+)(?:;ext=(\d+))?(?:;([\w-]+))?$' + #endregion Regex + + #region ReportType + if (-not ($Report)) + { + $Report = 'All' + } + #endregion ReportType + + # Cleanup + $ReportData = @() +} + +process +{ + #region Users + if (($Report -eq 'Users') -or ($Report -eq 'All')) + { + # Get Users with LineURI + $UsersLineURI = $null + $paramGetCsOnlineUser = @{ + ResultSize = 30000 + Verbose = $VerboseValue + Debug = $DebugValue + Filter = { + (LineURI -ne $null) + } + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + } + $paramSelectObject = @{ + Property = 'UserPrincipalName', 'LineURI', 'DisplayName', 'FirstName', 'LastName', 'Enabled', 'SipAddress' + Verbose = $VerboseValue + Debug = $DebugValue + } + $UsersLineURI = (Get-CsOnlineUser @paramGetCsOnlineUser | Select-Object @paramSelectObject) + + if ($UsersLineURI) + { + Write-Verbose -Message 'Processing User Numbers' + + foreach ($ReportingItem in $UsersLineURI) + { + $Matches = @() + + ($ReportingItem.PhoneNumber -match $LineURIRegex | Out-Null) + + $ReportingObject = (New-Object -TypeName System.Object) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'UserPrincipalName' -Value $ReportingItem.UserPrincipalName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'LineURI' -Value $ReportingItem.LineURI) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'DDI' -Value $Matches[1]) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Ext' -Value $Matches[2]) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'DisplayName' -Value $ReportingItem.DisplayName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'FirstName' -Value $ReportingItem.FirstName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'LastName' -Value $ReportingItem.LastName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'SipAddress' -Value $($ReportingItem.SipAddress -replace 'sip:', '')) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Enabled' -Value $ReportingItem.Enabled) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Type' -Value 'User') + + # Add to array + $null = ($ReportData += $ReportingObject) + } + } + } + #endregion Users + + #region MeetingRooms + if (($Report -eq 'MeetingRooms') -or ($Report -eq 'All')) + { + # Get meeting room numbers + $MeetingRoomLineURI = $null + + $paramGetCsMeetingRoom = @{ + ResultSize = 10000 + Verbose = $VerboseValue + Debug = $DebugValue + Filter = { + LineURI -ne $null + } + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + } + $paramSelectObject = @{ + Property = 'UserPrincipalName', 'LineURI', 'DisplayName', 'Enabled', 'SipAddress' + Verbose = $VerboseValue + Debug = $DebugValue + } + $MeetingRoomLineURI = (Get-CsMeetingRoom @paramGetCsMeetingRoom | Select-Object @paramSelectObject) + + if ($MeetingRoomLineURI) + { + Write-Verbose -Message 'Processing Meeting Room Numbers' + + foreach ($ReportingItem in $MeetingRoomLineURI) + { + $Matches = @() + + ($ReportingItem.PhoneNumber -match $LineURIRegex | Out-Null) + + $ReportingObject = (New-Object -TypeName System.Object) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'UserPrincipalName' -Value $ReportingItem.UserPrincipalName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'LineURI' -Value $ReportingItem.LineURI) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'DDI' -Value $Matches[1]) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Ext' -Value $Matches[2]) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'DisplayName' -Value $ReportingItem.DisplayName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'SipAddress' -Value $($ReportingItem.SipAddress -replace 'sip:', '')) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Enabled' -Value $ReportingItem.Enabled) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Type' -Value 'Meeting Room') + + # Remove existing User entry (Rooms have an user object as well) + if ($ReportData.UserPrincipalName -contains $ReportingItem.UserPrincipalName) + { + $ReportData = ($ReportData | Where-Object -FilterScript { + ($_.UserPrincipalName -ne $ReportingItem.UserPrincipalName) + }) + } + + # Add to array + $null = ($ReportData += $ReportingObject) + } + } + } + #endregion MeetingRooms + + #region ResourceAccounts + if (($Report -eq 'ResourceAccounts') -or ($Report -eq 'All')) + { + # Get online resource accounts + $OnlineApplicationInstanceLineURI = $null + + $paramGetCsOnlineApplicationInstance = @{ + Force = $true + ResultSize = 10000 + Verbose = $VerboseValue + Debug = $DebugValue + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + } + $paramSelectObject = @{ + Property = 'UserPrincipalName', 'DisplayName', 'PhoneNumber', 'ApplicationId', 'Enabled' + Verbose = $VerboseValue + Debug = $DebugValue + } + $OnlineApplicationInstanceLineURI = (Get-CsOnlineApplicationInstance @paramGetCsOnlineApplicationInstance | Where-Object -FilterScript { + ($_.PhoneNumber -ne $null) + } -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Select-Object @paramSelectObject) + + if ($OnlineApplicationInstanceLineURI) + { + Write-Verbose -Message 'Processing Online Application Instances (Resource Accounts) Numbers' + + foreach ($ReportingItem in $OnlineApplicationInstanceLineURI) + { + $Matches = @() + + ($ReportingItem.PhoneNumber -match $LineURIRegex | Out-Null) + + <# + Workaround: + + Get-CsOnlineApplicationInstance does not return an "Enabled" and "SipAddress" field, + so we try to re-use any existing object information + + Will not work all the time, only if regular users are reported as well! + #> + if ($ReportData.UserPrincipalName -contains $ReportingItem.UserPrincipalName) + { + # Cleanup + $WorkaroundInfo = $null + + $WorkaroundInfo = ($ReportData | Where-Object -FilterScript { + ($_.UserPrincipalName -eq $ReportingItem.UserPrincipalName) + } | Select-Object -Property 'Enabled', 'SipAddress') + + if (($WorkaroundInfo).Enabled) + { + $isAppEnabled = (($WorkaroundInfo).Enabled) + } + else + { + $isAppEnabled = 'unknown' + } + + if (($WorkaroundInfo).SipAddress) + { + $isSipAddress = (($WorkaroundInfo).SipAddress) + } + else + { + $isSipAddress = 'unknown' + } + } + + $ReportingObject = (New-Object -TypeName System.Object) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'UserPrincipalName' -Value $ReportingItem.UserPrincipalName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'LineURI' -Value $ReportingItem.PhoneNumber) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'DDI' -Value $Matches[1]) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Ext' -Value $Matches[2]) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'DisplayName' -Value $ReportingItem.DisplayName) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'SipAddress' -Value $isSipAddress) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Enabled' -Value $isAppEnabled) + $null = ($ReportingObject | Add-Member -MemberType NoteProperty -Name 'Type' -Value $( + if ($ReportingItem.ApplicationId -eq 'ce933385-9390-45d1-9512-c8d228074e07') + { + 'Auto Attendant Resource Account' + } + elseif ($ReportingItem.ApplicationId -eq '11cd3e2e-fccb-42ad-ad00-878b93575e07') + { + 'Call Queue Resource Account' + } + else + { + 'Unknown Resource Account' + } + )) + + # Remove existing User entry (Apps have an user object as well) + if ($ReportData.UserPrincipalName -contains $ReportingItem.UserPrincipalName) + { + $ReportData = ($ReportData | Where-Object -FilterScript { + ($_.UserPrincipalName -ne $ReportingItem.UserPrincipalName) + }) + } + + # Add to array + $null = ($ReportData += $ReportingObject) + } + } + } + #endregion ResourceAccounts + + # Sort the Array data, based on the LineURI object + $paramSortObject = @{ + Property = 'LineURI' + Verbose = $VerboseValue + Debug = $DebugValue + } + $ReportData = ($ReportData | Sort-Object @paramSortObject) + + #region Output + switch ($OutputType) + { + CSV + { + $FilePath = ($FilePath + '.csv') + + $paramConvertToCsv = @{ + Delimiter = ',' + NoTypeInformation = $true + Verbose = $VerboseValue + Debug = $DebugValue + ErrorAction = 'Continue' + WarningAction = 'Continue' + } + $PsCsv = ($ReportData | ConvertTo-Csv @paramConvertToCsv) + + $paramOutFile = @{ + FilePath = $FilePath + Force = $true + Append = $false + Encoding = 'utf8' + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + ($PsCsv | Out-File @paramOutFile) + + Write-Verbose -Message ('Your CSV report was saved to: {0}' -f $FilePath) + } + JSON + { + $FilePath = ($FilePath + '.json') + + $paramConvertToJson = @{ + Depth = 5 + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + $PsJson = @($ReportData | ConvertTo-Json @paramConvertToJson) + + $paramOutFile = @{ + FilePath = $FilePath + Force = $true + Append = $false + Encoding = 'utf8' + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + ($PsJson | Out-File @paramOutFile) + + Write-Verbose -Message ('Your JSON report was saved to: {0}' -f $FilePath) + } + YAML + { + if (Get-Command -Name 'ConvertTo-Yaml' -ErrorAction SilentlyContinue) + { + $FilePath = ($FilePath + '.yml') + + <# + Workaround for ConvertTo-Yaml + #> + $paramJsonWorkaround = @{ + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + $ReportData = @($ReportData | ConvertTo-Json @paramJsonWorkaround | ConvertFrom-Json @paramJsonWorkaround) + + $paramConvertToYaml = @{ + Data = $ReportData + Force = $true + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + $PsYaml = (ConvertTo-Yaml @paramConvertToYaml) + + $paramOutFile = @{ + FilePath = $FilePath + Force = $true + Append = $false + Encoding = 'utf8' + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + ($PsYaml | Out-File @paramOutFile) + + Write-Verbose -Message ('Your YAML report was saved to: {0}' -f $FilePath) + } + else + { + $paramWriteError = @{ + Exception = 'The ConvertTo-Yaml command was not found' + Message = 'Please ensure, that the ''powershell-yaml'' module is installed.' + Category = 'NotInstalled' + RecommendedAction = 'Please use ''Install-Module -Name powershell-yaml'' to install the required module!' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + } + } + XML + { + $FilePath = ($FilePath + '.xml') + + $paramConvertToXml = @{ + As = 'Stream' + InputObject = $ReportData + NoTypeInformation = $true + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + $PsXML = (ConvertTo-Xml @paramConvertToXml) + + $paramOutFile = @{ + FilePath = $FilePath + Force = $true + Append = $false + Encoding = 'utf8' + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + ($PsXML | Out-File @paramOutFile) + + Write-Verbose -Message ('Your XML report was saved to: {0}' -f $FilePath) + } + HTML + { + $FilePath = ($FilePath + '.html') + + $Header = @" +Microsoft Teams assigned phone number report + + + +"@ + + $htmlParams = @{ + Title = 'Microsoft Teams assigned phone number report' + Head = $Header + body = '

Microsoft Teams assigned phone number report

' + PreContent = '

The following Phone numbers are assigned in Microsoft Teams:

' + PostContent = '

Last updated: ' + ((Get-Date).ToUniversalTime()).ToString('HH:MM dd.MM.yyyy (UTC)') + '

' + Verbose = $VerboseValue + Debug = $DebugValue + } + $PsHtml = ($ReportData | ConvertTo-Html @htmlParams) + + $paramOutFile = @{ + FilePath = $FilePath + Force = $true + Append = $false + Encoding = 'utf8' + ErrorAction = 'Continue' + WarningAction = 'Continue' + Verbose = $VerboseValue + Debug = $DebugValue + } + ($PsHtml | Out-File @paramOutFile) + + Write-Verbose -Message ('Your HTML report was saved to: {0}' -f $FilePath) + } + CONSOLE + { + $paramFormatTable = @{ + AutoSize = $true + Property = 'UserPrincipalName', 'LineURI', 'DDI', 'Ext', 'DisplayName', 'Type' + Verbose = $VerboseValue + Debug = $DebugValue + } + ($ReportData | Format-Table @paramFormatTable) + + Write-Verbose -Message 'Formated Object was dumped' + } + default + { + $ReportData + + Write-Verbose -Message 'Unformated Object was dumped' + } + } + #endregion Output +} + +end +{ + # Cleanup + $ReportData = $null +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Get-TeamsServiceNumbers.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Get-TeamsServiceNumbers.ps1 new file mode 100644 index 0000000..ba180b2 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Get-TeamsServiceNumbers.ps1 @@ -0,0 +1,276 @@ +function Get-TeamsServiceNumbers +{ + <# + .SYNOPSIS + Get the Phone numbers assigned to Teams/SfB Services + + .DESCRIPTION + Get the Phone numbers assigned to Teams/SfB Services + Supported are AutoAttendant and/or CallQueue + + .PARAMETER AutoAttendant + Get the numbers assigned to AutoAttendant(s) + + .PARAMETER CallQueue + Get the numbers assigned to CallQueue(s) + + .PARAMETER All + Get all Numbers, assignee to AutoAttendant(s) and CallQueue(s) + + .PARAMETER LeaveTel + Normally the function dumps phone numbers with a stripped tel: + With this switch the function will dump it with the leading tel: + + .PARAMETER Export + Export the result to a CSV + + .PARAMETER Path + Path for the CSV Export + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -All + + Get all Services numbers, AutoAttendant(s) and CallQueue(s), and dump them to the terminal + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -All -Export -Path '.\TeamsServiceNumbers.csv' + + Get all Services numbers, AutoAttendant(s) and CallQueue(s), and export them to the given CSV file '.\TeamsServiceNumbers.csv' + TeamsServiceNumbers.csv is in the directory where the user is right now (and calls the function) + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -All -Export -Path 'c:\temp\TeamsServiceNumbers.csv' + + Get all Services numbers, AutoAttendant(s) and CallQueue(s), and export them to the given CSV file 'c:\temp\TeamsServiceNumbers.csv' + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -All -Export + + Get all Services numbers, AutoAttendant(s) and CallQueue(s), and export them to a CSV + The funtion will ask for the Path to the CSV File + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -AutoAttendant + + Get all AutoAttendant(s) Services numbers and dump them to the terminal + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -AA + + Get all AutoAttendant(s) Services numbers and dump them to the terminal + Same as above, but use the Alias (Shorter) + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -CallQueue + + Get all CallQueue(s) Services numbers and dump them to the terminal + + .EXAMPLE + PS C:\> Get-TeamsServiceNumbers -CQ + + Get all CallQueue(s) Services numbers and dump them to the terminal + Same as above, but use the Alias (Shorter) + + .NOTES + Additional information about the function. + #> + + [CmdletBinding(DefaultParameterSetName = 'AllNumbers', + ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ParameterSetName = 'AANumbers', + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [Alias('AA')] + [switch] + $AutoAttendant = $null, + [Parameter(ParameterSetName = 'CQNumbers', + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [Alias('CQ')] + [switch] + $CallQueue = $null, + [Parameter(ParameterSetName = 'AllNumbers', + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [Alias('Any')] + [switch] + $All, + [Parameter(ParameterSetName = '__AllParameterSets', + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [switch] + $LeaveTel = $null, + [Parameter(ParameterSetName = '__AllParameterSets', + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [Alias('ExportCsv', 'CSV')] + [switch] + $Export = $false + ) + + dynamicparam + { + if ($PSBoundParameters['Export']) + { + # The PATH parameter is only needed if -Export is given + $PathAttribute = New-Object System.Management.Automation.ParameterAttribute + $PathAttribute.Mandatory = $true + $PathAttribute.HelpMessage = "Path for the CSV Export:" + $PathAttribute.ValueFromPipeline = $true + $PathAttribute.ValueFromPipelineByPropertyName = $true + $PathAttribute.ParameterSetName = '__AllParameterSets' + $attributeCollection = New-Object System.Collections.ObjectModel.Collection[System.Attribute] + $attributeCollection.Add($PathAttribute) + $PathParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Path', [String], $attributeCollection) + $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary + $paramDictionary.Add('Path', $PathParam) + $paramDictionary + } + } + + begin + { + switch ($PsCmdlet.ParameterSetName) + { + 'AANumbers' + { + $AutoAttendant = $true + } + 'CQNumbers' + { + $CallQueue = $true + } + 'AllNumbers' + { + $All = $true + } + default + { + $All = $true + } + } + + if ($PSBoundParameters.Path) + { + $Path = $PSBoundParameters.Path + } + + $NumberReport = @() + } + + process + { + if (($AutoAttendant) -or ($All)) + { + foreach ($AA in (Get-CsAutoAttendant -ErrorAction Continue)) + { + foreach ($AppInstance in $AA.ApplicationInstances) + { + $AAName = $AA.Name + $AppPhoneNum = $null + + if ($LeaveTel) + { + $AppPhoneNum = ((Get-CsOnlineApplicationInstance -Identity $AppInstance -ErrorAction Continue).PhoneNumber) + } + else + { + $AppPhoneNum = (((Get-CsOnlineApplicationInstance -Identity $AppInstance -ErrorAction Continue).PhoneNumber).replace('tel:', '')) + } + + Write-Verbose ('AutoAttendant ' + $AA.Name + ' has ' + $AppPhoneNum + ' assigned') + + $NewRow = $null + $NewRow = [PSCustomObject][ordered]@{ + Name = ($AA.Name) + Number = ($AppPhoneNum) + Type = 'AutoAttendant' + } + + $NumberReport += $newrow + } + } + } + + if (($CallQueue) -or ($All)) + { + foreach ($CQ in (Get-CsCallQueue -ErrorAction Continue)) + { + foreach ($AppInstance in $CQ.ApplicationInstances) + { + $CQName = $null + $CQName = $CQ.Name + + $AppPhoneNum = $null + + if ($LeaveTel) + { + $AppPhoneNum = ((Get-CsOnlineApplicationInstance -Identity $AppInstance -ErrorAction Continue).PhoneNumber) + } + else + { + $AppPhoneNum = (((Get-CsOnlineApplicationInstance -Identity $AppInstance -ErrorAction Continue).PhoneNumber).replace('tel:', '')) + } + + Write-Verbose ('CallQueue ' + $CQ.Name + ' has ' + $AppPhoneNum + ' assigned') + + $NewRow = $null + $NewRow = [PSCustomObject][ordered]@{ + Name = ($CQ.Name) + Number = ($AppPhoneNum) + Type = 'CallQueue' + } + + $NumberReport += $newrow + } + } + } + } + + end + { + if (($PSBoundParameters['Export']) -or ($Path)) + { + $NumberReport | Export-Csv -Path $Path -NoTypeInformation -Encoding UTF8 -ErrorAction Stop -WarningAction Continue + + Write-Verbose -Message $NumberReport + } + else + { + $NumberReport + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Get-bdcMicrosoftTeamsReporting.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Get-bdcMicrosoftTeamsReporting.ps1 new file mode 100644 index 0000000..c1d8f50 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Get-bdcMicrosoftTeamsReporting.ps1 @@ -0,0 +1,446 @@ +function Get-bdcMicrosoftTeamsReporting +{ + <# + .SYNOPSIS + Get a Report for all Microsoft Teams Teams + + .DESCRIPTION + Get a Report for all Microsoft Teams Teams + + .PARAMETER Connect + Executes Connect-MicrosoftTeams for you + + .PARAMETER Disconnect + Executes Disconnect-MicrosoftTeams for you as soon as the report is generated + + .PARAMETER GiphyDetails + Include Giphy Details in the report + + .PARAMETER MemesDetails + Include Memes Details in the report + + .PARAMETER GuestDetails + Include Guest Details in the report + + .PARAMETER Detailed + Report some more Details about the Teams. + + .PARAMETER AllDetails + All of the Details are reported, might be a bit verbose for some. + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting + + Get a Report for all Microsoft Teams Teams + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting | Where-Object -FilterScript { + $_.owners -eq 0 + } | Select-Object -ExpandProperty DisplayName + + Find all Teams without an owner. + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting | Where-Object -FilterScript { + $_.owners -eq 1 + } | Select-Object -ExpandProperty DisplayName | ForEach-Object -Process { + Write-Warning -Message "Looks like $_ is an orphaned objects, it has no owner!" -ErrorAction Continue + } + + Find all Teams without an owner. Teams without an owner are bad teams... + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting | Where-Object -FilterScript { + ($_.Members -eq 0) -and ($_.Guests -eq 0) + } | Select-Object -ExpandProperty DisplayName | ForEach-Object -Process { + Write-Warning -Message "Looks like $_ has no members and guests!" -ErrorAction Continue + } + + Find Teams without members and guests, empty teams are boring and, more or less, useless + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting | Where-Object -FilterScript { + ($_.Archived -eq $true) -and ($_.ShowInTeamsSearchAndSuggestions -eq $true) + } | Select-Object -ExpandProperty DisplayName | ForEach-Object -Process { + Write-Warning -Message "Looks like $_ is archived but searchable!" -ErrorAction Continue + } + + Find archived Teams that are still searchable, might not be a bad thing... + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -Connect -Disconnect + + Get a Report for all Microsoft Teams Teams, invokes the Connect-MicrosoftTeams and Disconnect-MicrosoftTeams for you + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -AllDetails + + Get a Report for all Microsoft Teams Teams, with all the details (very verbose) + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -GiphyDetails + + Get a Report for all Microsoft Teams Teams, and include Giphy Details + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -MemesDetails + + Get a Report for all Microsoft Teams Teams, and include Memes Details + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -GiphyDetails -MemesDetails + + Get a Report for all Microsoft Teams Teams, and include Giphy and Memes Details + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -GuestDetails + + Get a Report for all Microsoft Teams Teams, and include Guest Details + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -Detailed + + Get a Report for all Microsoft Teams Teams, with more details then the regular report + + .EXAMPLE + PS C:\> Get-bdcMicrosoftTeamsReporting -Detailed -GuestDetails + + Get a Report for all Microsoft Teams Teams, with more details then the regular report and Guest Details + + .NOTES + Reworked function to deliver everything we need to have for our Office 365 reporting service. + See the examples above and you will get an idea what you can do with filtering :-) + + .LINK + https://www.powershellgallery.com/packages/MicrosoftTeams/1.0.3 + + .LINK + https://github.com/MicrosoftDocs/office-docs-powershell/tree/master/teams + + .LINK + Get-Team + + .LINK + Get-TeamUser + + .LINK + Get-TeamChannel + + .LINK + Connect-MicrosoftTeams + + .LINK + Disconnect-MicrosoftTeams + + .LINK + https://aka.ms/InstallModule + + .LINK + https://github.com/tomarbuthnot/Microsoft-Teams-PowerShell + + .LINK + https://opensource.org/licenses/BSD-3-Clause + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('DoConnect')] + [switch] + $Connect, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('DoDisconnect')] + [switch] + $Disconnect, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('IncludeGiphyDetails', 'Giphy')] + [switch] + $GiphyDetails, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('IncludeMemesDetails', 'Memes')] + [switch] + $MemesDetails, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('IncludeGuestDetails', 'Guest')] + [switch] + $GuestDetails, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('DetailedReport')] + [switch] + $Detailed, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('VerboseReport')] + [switch] + $AllDetails + ) + + begin + { + #region Connect + if ($Connect) + { + # Logon + $null = (Connect-MicrosoftTeams) + } + #endregion Connect + + # Crete an empty Report variable + $MicrosoftTeamsReport = @() + } + + process + { + # Get all Microsoft Teams Teams and loop over them + try + { + Get-Team -ErrorAction Stop | ForEach-Object -Process { + try + { + Write-Verbose -Message ('Generate the Report for the Microsoft Teams Team {0}' -f $_.DisplayName) + + # Cleanup + $TeamUserDetails = $null + + # Get the User information for the Microsoft Teams Team and save it for reuse + $TeamUserDetails = $null + $TeamUserDetails = (Get-TeamUser -GroupId $_.GroupID -ErrorAction Stop) + + # Get the Channel information for the Microsoft Teams Team + $TeamChannelDetails = $null + $TeamChannelDetails = ((Get-TeamChannel -GroupId $_.GroupID -ErrorAction Stop).count) + + # Put all details into an object + $SingleTeamReport = (New-Object -TypeName PSobject) + + #region FillSingleTeamReport + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'DisplayName' -Value $_.DisplayName + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Description' -Value $_.Description + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Visibility' -Value $_.Visibility + + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Archived' -Value $_.Archived + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'ShowInTeamsSearchAndSuggestions' -Value $_.ShowInTeamsSearchAndSuggestions + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Channels' -Value $TeamChannelDetails + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Owners' -Value (($TeamUserDetails | Where-Object -FilterScript { + $_.Role -like 'owner' + }).count) + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Members' -Value (($TeamUserDetails | Where-Object -FilterScript { + $_.Role -like 'member' + }).count) + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Guests' -Value (($TeamUserDetails | Where-Object -FilterScript { + $_.Role -like 'guest' + }).count) + + #region GiphyDetails + if ($GiphyDetails -or $AllDetails) + { + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowGiphy' -Value $_.AllowGiphy + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'GiphyContentRating' -Value $_.GiphyContentRating + } + #endregion GiphyDetails + + #region MemesDetails + if ($MemesDetails -or $AllDetails) + { + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowStickersAndMemes' -Value $_.AllowStickersAndMemes + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowCustomMemes' -Value $_.AllowCustomMemes + } + #endregion MemesDetails + + #region GuestDetails + if ($GuestDetails -or $AllDetails) + { + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowGuestCreateUpdateChannels' -Value $_.AllowGuestCreateUpdateChannels + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowGuestDeleteChannels' -Value $_.AllowGuestDeleteChannels + } + #endregion GuestDetails + + #region DetailedReport + if ($Detailed -or $AllDetails) + { + # Based on the idea of Tom Arbuthnot (https://github.com/tomarbuthnot/Microsoft-Teams-PowerShell) + $DescriptionWordCount = (($_.Description | Out-String | Measure-Object -Word).words) + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'DescriptionWordCount' -Value $DescriptionWordCount + + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'DescriptionScore' -Value $(if ($DescriptionWordCount -eq 0) + { + 'Terrible' + } + elseif ($DescriptionWordCount -le 2) + { + 'Poor' + } + elseif ($DescriptionWordCount -le 5) + { + 'OK' + } + elseif ($DescriptionWordCount -ge 6) + { + 'Good' + } + else + { + 'Unknown' + } + ) + + # As requested by Peter Duda + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'Classification' -Value $(if ($_.Classification) + { + $_.Classification + } + else + { + 'None' + } + ) + + # New since 2020/01 + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'MailNickName' -Value $(if ($_.MailNickName) + { + $_.MailNickName + } + else + { + 'None' + } + ) + + # Verbose reporting + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowCreateUpdateChannels' -Value $_.AllowCreateUpdateChannels + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowDeleteChannels' -Value $_.AllowDeleteChannels + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowAddRemoveApps' -Value $_.AllowAddRemoveApps + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowCreateUpdateRemoveTabs' -Value $_.AllowCreateUpdateRemoveTabs + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowCreateUpdateRemoveConnectors' -Value $_.AllowCreateUpdateRemoveConnectors + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowUserEditMessages' -Value $_.AllowUserEditMessages + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowUserDeleteMessages' -Value $_.AllowUserDeleteMessages + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowOwnerDeleteMessages' -Value $_.AllowOwnerDeleteMessages + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowTeamMentions' -Value $_.AllowTeamMentions + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'AllowChannelMentions' -Value $_.AllowChannelMentions + } + #endregion DetailedReport + + #region FinalValue + $SingleTeamReport | Add-Member -MemberType NoteProperty -Name 'GroupId' -Value $_.GroupId + #endregion FinalValue + #endregion FillSingleTeamReport + + # Append to the Report + $MicrosoftTeamsReport += $SingleTeamReport + } + catch + { + #region WarningHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteWarning = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + WarningAction = 'Continue' + } + Write-Warning @paramWriteWarning + #region WarningHandler + } + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Just in case + Exit 1 + #region ErrorHandler + } + } + + end + { + #region Disconnect + if ($Disconnect) + { + # Logoff + $null = (Disconnect-MicrosoftTeams -Confirm:$false) + } + #endregion Disconnect + + #region ShowReport + # Dump the Report + $MicrosoftTeamsReport + #endregion ShowReport + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-OptimizeAppsForTerminalService.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-OptimizeAppsForTerminalService.ps1 new file mode 100644 index 0000000..23321f4 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-OptimizeAppsForTerminalService.ps1 @@ -0,0 +1,300 @@ +#requires -Version 3.0 -Modules BitsTransfer -RunAsAdministrator +<# + .SYNOPSIS + Download, install, and Tweak System and Apps for Terminal Server use + + .DESCRIPTION + Download, install, and Tweak System and Apps for Terminal Server (WVD/VDI/WDS) use + + .NOTES + Early testing release - Future releases might get some parameters + + Changelog: + 1.0.0: Initial Release + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download, install, and Tweak System and Apps for Terminal Server use' + + # Default URL (Assume we use 64Bit) + [string]$FSLogixUrl = 'https://aka.ms/fslogix_download' + + #region PossibleParameters + # Where to Store it + [string]$Target = ($env:Temp) + + # File Name + [string]$TargetName = 'fslogix.zip' + + # Install Switch + [string]$Arguments = '/install /quiet /norestart' + #endregion PossibleParameters + + #region Defaults + # Set the full path of the downloaded installer + [string]$InstallerPackage = ($Target + '\' + $TargetName) + + [string]$InstallerDestination = (($InstallerPackage).Replace('.zip', '')) + [string]$InstallerExecutable = ($InstallerDestination + '\x64\Release\FSLogixAppsSetup.exe') + $SCT = 'SilentlyContinue' + $STP = 'Stop' + #endregion Defaults +} + +process +{ + Write-Verbose -Message ('Downloading {0} to {1}' -f $TargetName, $InstallerPackage) + + # Use BitsTransfer to download the latest installer + $paramStartBitsTransfer = @{ + Source = $FSLogixUrl + Destination = $InstallerPackage + Priority = 'High' + TransferPolicy = 'Always' + ErrorAction = $STP + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + + # Expand FSLogix Installer + $paramTestPath = @{ + Path = $InstallerPackage + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramTestPath = @{ + Path = $InstallerDestination + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $InstallerDestination + Force = $true + Confirm = $false + ItemType = 'Directory' + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + try + { + # Expand-Archive is to buggy! + $null = (Add-Type -AssemblyName System.IO.Compression.FileSystem -ErrorAction $STP) + $null = ([IO.Compression.ZipFile]::ExtractToDirectory($InstallerPackage, $InstallerDestination)) + } + catch + { + # OK! That is crappy, but it still works well as a fallback. + $shellApp = (New-Object -ComObject Shell.Application -ErrorAction $STP) + $shellZip = $shellApp.NameSpace([String]$InstallerPackage) + $shellDest = $shellApp.NameSpace($InstallerDestination) + $shellDest.CopyHere($shellZip.items()) + } + } + else + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # We are done + break + } + + # Install FSLogix + $paramTestPath = @{ + Path = $InstallerExecutable + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $InstallerExecutable + ErrorAction = $SCT + } + $InstallerVersion = ((Get-ItemProperty @paramGetItemProperty).VersionInfo.ProductVersion) + + Write-Verbose -Message ('Running FSLogix installer version {0}' -f $InstallerVersion) + + $paramStartProcess = @{ + FilePath = $InstallerExecutable + ArgumentList = $Arguments + Wait = $true + PassThru = $true + ErrorAction = $STP + } + $InstallerProcess = (Start-Process @paramStartProcess) + + if (($InstallerProcess | Select-Object -ExpandProperty ExitCode) -eq 0) + { + Write-Verbose -Message ('Installed FSLogix version {0}' -f $InstallerVersion) + } + else + { + Write-Warning -Message ('Installer exit code {0}.' -f $InstallerProcess.ExitCode) + } + + Write-Verbose -Message ('Removing file: {0}' -f $InstallerPackage) + + # Remove the downloaded Installaer Package + $paramRemoveItem = @{ + Path = $InstallerPackage + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + + # Install the expanded stuff + $paramRemoveItem = @{ + Path = $InstallerDestination + Recurse = $true + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + + # Legacy HKLM Path for WVD/VDI/WDS Environment + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Citrix\PortICA' + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Ensure that the registry path exists + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Teams' + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Tell Microsoft Teams that it runs in an WVD/VDI/WDS Environment + # Source: https://docs.microsoft.com/en-us/azure/virtual-desktop/teams-on-wvd + $paramNewItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Teams' + Name = 'IsWVDEnvironment' + PropertyType = 'DWORD' + Value = 1 + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + + # Ensure that the registry path exists + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32' + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Do not start Microsoft Teams after Login + $paramNewItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32' + Name = 'Teams' + PropertyType = 'Binary' + Value = ([byte[]](0x01, 0x00, 0x00, 0x00, 0x1a, 0x19, 0xc3, 0xb9, 0x62, 0x69, 0xd5, 0x01)) + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # We are done + break + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-TweakTeamsClientFirewall.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-TweakTeamsClientFirewall.ps1 new file mode 100644 index 0000000..fd79c23 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-TweakTeamsClientFirewall.ps1 @@ -0,0 +1,137 @@ +#requires -Version 3.0 -Modules NetSecurity -RunAsAdministrator +<# + .SYNOPSIS + Tweak the Firewall Rules for Microsoft Teams clients + + .DESCRIPTION + Tweak the Firewall Rules for Microsoft Teams clients for all users that have it installed + + .NOTES + Early testing release + + Changelog: + 1.0.0: Initial Release + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Tweak the Firewall Rules for Microsoft Teams clients for all users that have it installed' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults +} + +process +{ + # Creates firewall rules for Microsoft Teams + $AllUsers = $null + + $paramJoinPath = @{ + Path = $env:SystemDrive + ChildPath = 'Users' + ErrorAction = $SCT + } + $paramGetChildItem = @{ + Path = (Join-Path @paramJoinPath) + ErrorAction = $SCT + Exclude = 'Public', 'ADMINI~*' + } + $AllUsers = (Get-ChildItem @paramGetChildItem) + + if ($null -ne $AllUsers) + { + foreach ($SingleUser in $AllUsers) + { + # Cleanup + $FullTeamsPath = $null + + # get the Executable + $paramJoinPath = @{ + Path = $SingleUser.FullName + ChildPath = 'AppData\Local\Microsoft\Teams\Current\Teams.exe' + ErrorAction = $SCT + } + $FullTeamsPath = (Join-Path @paramJoinPath) + + $paramTestPath = @{ + Path = $FullTeamsPath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetNetFirewallApplicationFilter = @{ + Program = $FullTeamsPath + ErrorAction = $SCT + } + if (-not (Get-NetFirewallApplicationFilter @paramGetNetFirewallApplicationFilter)) + { + # Cleanup + $NetFirewallRuleName = $null + + # Apply the Rulename + $NetFirewallRuleName = ('Teams.exe for user {0}' -f $SingleUser.Name) + + 'UDP', 'TCP' | ForEach-Object -Process { + $paramNewNetFirewallRule = @{ + DisplayName = $NetFirewallRuleName + Direction = 'Inbound' + Profile = 'Any' + Program = $FullTeamsPath + Action = 'Allow' + Protocol = $_ + Enabled = 'True' + Confirm = $false + ErrorAction = $SCT + } + $null = (New-NetFirewallRule @paramNewNetFirewallRule) + } + + # Cleanup + $NetFirewallRuleName = $null + } + } + + # Cleanup + $FullTeamsPath = $null + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-mtrDisableModernAuthentication.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-mtrDisableModernAuthentication.ps1 new file mode 100644 index 0000000..903917a --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Invoke-mtrDisableModernAuthentication.ps1 @@ -0,0 +1,184 @@ +function Invoke-mtrDisableModernAuthentication +{ + <# + .SYNOPSIS + Disable Modern Authentication for a Microsoft Teams Room Device Account + + .DESCRIPTION + Disable Modern Authentication for a Microsoft Teams Room Device Account + It dsables it in Exchange Online and Skype for Business Online. It also configures the tenant to do so, if needed. + + .PARAMETER Identity + The Microsoft Teams Rooms (MTR) Account Search String + + .EXAMPLE + PS C:\> .\Invoke-mtrDisableModernAuthentication.ps1 -Identity 'MyTeamRoom' + + .EXAMPLE + PS C:\> .\Invoke-mtrDisableModernAuthentication.ps1 -Identity 'TeamRoom@contoso.com' + + .NOTES + Just a quick and dirty tool to do the job, nothing fancy and without a real error handling! + -> Use at your own risk! + + You need to be a tenant admin to configure all the things + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param + ( + [Parameter(Mandatory, HelpMessage = 'The Microsoft Teams Rooms (MTR) Account Search String', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [Alias('SearchString', 'mtrAccount')] + [string] + $Identity + ) + + begin + { + #region Defaults + $STP = 'Stop' + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region GeneralParameters + $RemovePSSessionDefaultParams = @{ + Confirm = $false + ErrorAction = $SCT + } + + $RemoveModuleDefaultParams = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + #endregion GeneralParameters + + Write-Verbose -Message 'Message' + } + + process + { + #region ConnectAzureAD + $null = (Connect-AzureAD) + #endregion ConnectAzureAD + + #region ConnectSkypeForBusinessOnline + # We use a crappy workaround, because the Modern Auth window never shows up to querry the admin UPN, and I do NOT trust the command to querry it + $SkypeForBusinessSession = (New-CsOnlineSession -UserName (Read-Host -Prompt 'Please enter the admin principal name (ex. admin@contoso.com)')) + $paramImportPSSession = @{ + Session = $SkypeForBusinessSession + DisableNameChecking = $true + AllowClobber = $true + } + $null = (Import-PSSession @paramImportPSSession) + #endregion ConnectSkypeForBusinessOnline + + #region ConnectExchangeOnline + # We use the ExchangeOnlineShell Module from the Gallery + if (-not (Get-Command -Name Get-Mailbox -ErrorAction $SCT)) + { + $paramConnectExchangeOnlineShell = @{ + Confirm = $false + WarningAction = $SCT + ErrorAction = $STP + } + $null = (Connect-ExchangeOnlineShell @paramConnectExchangeOnlineShell) + } + #endregion ConnectExchangeOnline + + #region CheckModernAuth + # Do we have Modern Auth enabled Global? + if ((Get-OrganizationConfig | Select-Object -ExpandProperty OAuth2ClientProfileEnabled) -eq $true) + { + # Disconnect Modern Authentication (For a single user) - In this case the MTR + $paramRevokeAzureADUserAllRefreshToken = @{ + ObjectId = (Get-AzureADUser -SearchString $Identity | Select-Object -ExpandProperty objectId) + ErrorAction = $SCT + } + $null = (Revoke-AzureADUserAllRefreshToken @paramRevokeAzureADUserAllRefreshToken) + $null = (Revoke-AzureADUserAllRefreshToken @paramRevokeAzureADUserAllRefreshToken) + + # Allow non Modern Auth in Skype for Business + if ((Get-CsOAuthConfiguration -ErrorAction $SCT | Select-Object -ExpandProperty ClientAdalAuthOverride) -ne 'Allowed') + { + $paramSetCsOAuthConfiguration = @{ + ClientAdalAuthOverride = 'Allowed' + Confirm = $false + ErrorAction = $SCT + } + $null = (Set-CsOAuthConfiguration @paramSetCsOAuthConfiguration) + } + } + else + { + # Shame on you! + Write-Warning -Message 'Looks like Modern Auth is not enabled for this tenant!' -WarningAction $STP + } + #endregion CheckModernAuth + + #region DisconnectAzureAD + $null = (Disconnect-AzureAD -Confirm:$false -ErrorAction $SCT) + #endregion DisconnectAzureAD + + #region DisconnectSkypeForBusiness + $paramRemoveModule = @{ + Name = (Get-Command -Name Set-CsOAuthConfiguration -ErrorAction $SCT | Select-Object -ExpandProperty Source) + Force = $true + ErrorAction = $SCT + } + + $null = (Remove-Module @paramRemoveModule) + $null = ($SkypeForBusinessSession.Id | Remove-PSSession @RemovePSSessionDefaultParams) + #endregion DisconnectSkypeForBusiness + + #region DisconnectExchangeOnline + $ExchangeSessionID = (Get-PSSession | Where-Object { + $_.ComputerName -eq 'outlook.office365.com' + } | Select-Object -ExpandProperty Id) + + if ($ExchangeSessionID) + { + $paramDisconnectExchangeOnlineShell = @{ + SessionID = $ExchangeSessionID + Confirm = $false + } + $null = (Disconnect-ExchangeOnlineShell @paramDisconnectExchangeOnlineShell) + } + + # Will be removed soon (Disconnect-ExchangeOnlineShell will handle this for us!) + $RemoveModuleName = (Get-Command -Name Get-OrganizationConfig -ErrorAction $SCT | Select-Object -ExpandProperty Source) + + if ($RemoveModuleName) + { + $paramRemoveModule = @{ + Name = $RemoveModuleName + Force = $true + ErrorAction = $SCT + } + $null = (Remove-Module @RemoveModuleDefaultParams) + } + #endregion DisconnectExchangeOnline + } + + end + { + #region FinalCleanup + # Just in case: We remove all sessions that might still be around + $null = ((Get-PSSession -ErrorAction $SCT | Where-Object { + $_.ComputerName -eq 'outlook.office365.com' + }) | Remove-PSSession @RemovePSSessionDefaultParams) + + $null = ((Get-PSSession -ErrorAction $SCT | Where-Object { + $_.ComputerName -like 'admin*.online.lync.com' + }) | Remove-PSSession @RemovePSSessionDefaultParams) + + # Remove the Modules (Here just in case we missed something above) + $null = (Remove-Module -Name (Get-Command -Name Connect-ExchangeOnlineShell -ErrorAction $SCT | Select-Object -ExpandProperty Source) @RemoveModuleDefaultParams) + $null = (Remove-Module -Name (Get-Command -Name Disconnect-AzureAD -ErrorAction $SCT | Select-Object -ExpandProperty Source) @RemoveModuleDefaultParams) + $null = (Remove-Module -Name (Get-Command -Name New-CsOnlineSession -ErrorAction $SCT | Select-Object -ExpandProperty Source) @RemoveModuleDefaultParams) + #endregion FinalCleanup + } +} diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/LICENSE b/Powershell/PowerShell-collection/MicrosoftTeams/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/New-AITMicrosoftTeams.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/New-AITMicrosoftTeams.ps1 new file mode 100644 index 0000000..b406f01 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/New-AITMicrosoftTeams.ps1 @@ -0,0 +1,448 @@ +#requires -Version 3.0 + +<# + .SYNOPSIS + Creates a new Microsoft Teams team with the MicrosoftTeams Module. + + .DESCRIPTION + Creates a new Microsoft Teams team with the MicrosoftTeams Module. + The new team will be backed by a newly created unified group and SharePoint Online Site. + + The script depends on Microsoft's Version 0.9.6 of the MicrosoftTeams Module. + Please note: Not all authentications methods of the latest MicrosoftTeams Module are supported! + + .PARAMETER msTeamsCreds + Specifies a PSCredential object. For more information about the PSCredential object, type Get-Help Get-Credential. + The PSCredential object provides the user ID and password for organizational ID credentials. + + .PARAMETER mfa + Use the web based authentication. Supports MFA and prevents issues in non ADFS implementations. + + .PARAMETER DisplayName + Todeam display name. Team Name Characters Limit is 256. + + .PARAMETER Alias + Same as displayName without any spaces. Team Alias Characters Limit is 64 + + .PARAMETER Description + Team description. Team Description Characters Limit is 1024. + + .PARAMETER AccessType + Team access type. Valid values are "Private" and "Public". Default is "Private". (This parameter has the same meaning as -AccessType in New-UnifiedGroup.) + + .PARAMETER AddCreatorAsMember + This setting lets you decide if you will be added as a member of the team. The default is false. + + .PARAMETER Owner + UPN/Mail of the Teams Owner, multiple values are supported! + + .PARAMETER User + member Users for the Group, Please use UPN or Mail. + Multiple values are supported. + + .EXAMPLE + PS C:\> .\New-AITMicrosoftTeams -mfa -DisplayName 'Contoso Support' + + Creates the Microsoft Team 'Contoso Support'. Uses Weblog (supports MFA) + + .EXAMPLE + PS C:\> .\New-AITMicrosoftTeams -msTeamsCreds $O365 -DisplayName 'Contoso Support' + + Creates the Microsoft Team 'Contoso Support'. Uses existing credentials stored in the variable $O365 to authenticate. + This might be the perfect way for automation, but use stored credentials might also be insecure. + + .EXAMPLE + PS C:\> .\New-AITMicrosoftTeams -DisplayName 'Contoso Support' + + Creates the Microsoft Team 'Contoso Support' + + .EXAMPLE + PS C:\> .\New-AITMicrosoftTeams -DisplayName 'Contoso Support' -Alias 'AITSupport' + + Creates the Microsoft Team 'Contoso Support' with an Alias 'AITSupport' + + .EXAMPLE + PS C:\> .\New-AITMicrosoftTeams -DisplayName 'Contoso Info-pool' -AccessType 'public' + + Creates the Microsoft Team 'Contoso Info-pool', public mean open to join for every member of the organization. + + .EXAMPLE + PS C:\> .\New-AITMicrosoftTeams -DisplayName 'Contoso Development' -Description 'Contoso IT Development Team' -Owner 'john.doe@acontoso.com' + + Creates the Microsoft Team 'Contoso Development', sets a description and add 'john.doe@contoso.com' as Owner. + + .EXAMPLE + PS C:\> .\New-AITMicrosoftTeams -DisplayName 'Contoso Core Dev' -AddCreatorAsMember $true + + Creates the Microsoft Team 'Contoso Core Dev' and adds the creator to the new Team. + + .EXAMPLE + PS C:\> Install-Module -Name MicrosoftTeams + + Install the dependency Module from Microsoft via PowerShellGet. + + .NOTES + Releasenotes: + 1.0.3 2019-04-26: Fix Module Statement to use the correct version (0.9.6) to avoid issues with our workaround. + 1.0.2 2019-02-05: Reintroduce the -MFA switch to support the web based authentication. Prevent issues in non ADFS implementations. + 1.0.1 2019-02-04: Add workaround for AddCreatorAsMember Bug (Creator is added as owner all the time) + 1.0.0 2018-12-31: Internal Release + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + The script depends on Microsoft's Version 0.9.6 of the MicrosoftTeams PowerShell Module. + The MicrosoftTeams PowerShell Module GA Version (1.0.0) is not yet tested! + + Install it with PowerShellGet: + PS C:\> Install-Module -Name MicrosoftTeams -RequiredVersion 0.9.6 + + .LINK + https://www.powershellgallery.com/packages/MicrosoftTeams/0.9.6 + + .LINK + https://aka.ms/InstallModule +#> +[CmdletBinding(DefaultParameterSetName = 'MFA', + ConfirmImpact = 'None')] +param +( + [Parameter(ParameterSetName = 'Credentials', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [System.Management.Automation.Credential()] + [Alias('TeamsCredentials', 'TeamsAdminCredentials', 'Office365creds')] + [pscredential] + $msTeamsCreds, + [Parameter(ParameterSetName = 'MFA', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [Alias('UseMFA')] + [switch] + $mfa, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Team display name.')] + [ValidateNotNullOrEmpty()] + [Alias('TeamsDisplayName')] + [string] + $DisplayName, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('TeamsAlias')] + [string] + $Alias, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 3)] + [Alias('TeamsDescription')] + [string] + $Description, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 4)] + [ValidateSet('HiddenMembership', 'Private', 'Public', IgnoreCase = $true)] + [Alias('TeamsAccessType')] + [string] + $AccessType = 'Private', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 5)] + [Alias('AddCreatorAsTeamsMember')] + [switch] + $AddCreatorAsMember = $false, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 6)] + [Alias('TeamsOwner')] + [string[]] + $Owner, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 7)] + [Alias('TeamsUser', 'TeamsMember')] + [string[]] + $User +) + +begin +{ + #region VersionRequirement + try + { + $paramRemoveModule = @{ + Name = 'MicrosoftTeams' + Force = $true + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + } + $null = (Remove-Module @paramRemoveModule) + + $paramImportModule = @{ + Name = 'MicrosoftTeams' + MaximumVersion = '0.9.6' + Force = $true + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $null = (Import-Module @paramImportModule) + } + catch + { + $paramWriteError = @{ + Message = 'Microsoft´s Version 0.9.6 of the MicrosoftTeams PowerShell Module' + ErrorAction = 'Stop' + Category = 'NotInstalled' + Exception = 'Required Module not found' + RecommendedAction = 'Please install Version 0.9.6 of the MicrosoftTeams PowerShell Module via Install-Module -Name MicrosoftTeams -RequiredVersion 0.9.6' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + break + } + #endregion VersionRequirement + + #region AuthChecker + if (($msTeamsCreds) -and ($mfa)) + { + $paramWriteError = @{ + Message = 'You have selected muliple authentication methods. This is not valid' + Exception = 'Muliple authentication methods selected' + Category = 'AuthenticationError' + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + break + } + #endregion AuthChecker + + #region Defaults + #region AccessType + if (-not ($AccessType)) + { + $AccessType = 'Private' + } + #endregion AccessType + + #region AddCreatorAsMember + if (-not ($AddCreatorAsMember)) + { + $AddCreatorAsMember = $false + } + #endregion AddCreatorAsMember + #endregion defaults +} + +process +{ + if ($pscmdlet.ShouldProcess($DisplayName, 'Create')) + { + try + { + #region Authentication + if (-not ($mfa)) + { + #region CredentialHandler + if (-not ($msTeamsCreds)) + { + # Get the credentials / Use it within the script only + $script:msTeamsCreds = (Get-Credential -Message 'Please use credentials with Teams Admin capabilities.') + } + #endregion CredentialHandler + + #region ConnectMicrosoftTeams + $paramConnectMicrosoftTeams = @{ + Credential = $msTeamsCreds + Confirm = $false + ErrorAction = 'Stop' + } + $null = (Connect-MicrosoftTeams @paramConnectMicrosoftTeams) + #endregion ConnectMicrosoftTeams + } + else + { + #region ConnectMicrosoftTeams + # Use the Web login + $paramConnectMicrosoftTeams = @{ + Confirm = $false + ErrorAction = 'Stop' + } + $null = (Connect-MicrosoftTeams @paramConnectMicrosoftTeams) + #endregion ConnectMicrosoftTeams + } + #endregion Authentication + + #region NewTeam + #region SplatDefaults + $paramNewTeam = @{ + DisplayName = $DisplayName + Visibility = $AccessType + ErrorAction = 'Stop' + } + #endregion SplatDefaults + + #region Optionals + if (($msTeamsCreds.UserName) -and ($AddCreatorAsMember -eq $true)) + { + $paramNewTeam | Add-Member -MemberType NoteProperty -Name Owner -Value $msTeamsCreds.UserName + } + + if ($Alias) + { + $paramNewTeam | Add-Member -MemberType NoteProperty -Name Alias -Value $Alias + } + + if ($Description) + { + $paramNewTeam | Add-Member -MemberType NoteProperty -Name Description -Value $Description + } + #region Optionals + + #region CreateTeam + $NewTeam = (New-Team @paramNewTeam) + #endregion CreateTeam + + if (-not ($NewTeam.GroupId)) + { + Write-Error -Message ('Error while try to create {0}' -f $DisplayName) + } + else + { + Write-Verbose -Message "The new Team id is $($NewTeam.GroupId)" + + #region BugWorkAround + #BUG: There is a bug in the AddCreatorAsMember implemntation of Microsoft + if ($AddCreatorAsMember -eq $false) + { + Write-Verbose -Message 'Workaround: Workaround for the AddCreatorAsMember of the Microsoft MicrosoftTeams Module' + Remove-TeamUser -GroupId $NewTeam.GroupId -User $msTeamsCreds.UserName -ErrorAction SilentlyContinue + } + #endregion BugWorkAround + + #region SetOwner + if ($Owner) + { + foreach ($Admin in $Owner) + { + try + { + $paramAddTeamUser = @{ + GroupId = $NewTeam.GroupId + User = $Admin + Role = 'Owner' + ErrorAction = 'Stop' + } + $null = (Add-TeamUser @paramAddTeamUser) + } + catch + { + Write-Warning -Message ('Unable to add {0} as owner to the Team {1}' -f $Admin, $DisplayName) + } + } + } + else + { + Write-Warning -Message ('The Team {0} has no owner!' -f $DisplayName) + } + #endregion SetOwner + + #region Setmember + if ($User) + { + foreach ($Member in $User) + { + try + { + $paramAddTeamUser = @{ + GroupId = $NewTeam.GroupId + User = $Member + Role = 'Member' + ErrorAction = 'Stop' + } + $null = (Add-TeamUser @paramAddTeamUser) + } + catch + { + Write-Warning -Message ('Unable to add {0} as member to the Team {1}' -f $Member, $DisplayName) + } + } + } + #endregion Setmember + } + #endregion NewTeam + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + finally + { + #region Cleanup + $null = (Disconnect-MicrosoftTeams -Confirm:$false) + #endregion Cleanup + } + } +} + +end +{ + Write-Verbose -Message ('Created the Team {0}' -f $DisplayName) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/ProjectTeamStructure.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/ProjectTeamStructure.ps1 new file mode 100644 index 0000000..d5670e6 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/ProjectTeamStructure.ps1 @@ -0,0 +1,719 @@ +<# + .SYNOPSIS + Create a Project team in Teams with folder structure in files tab + + .TeamsDescription + Create a Project team in Teams with folder structure in files tab + Based on Alexander Holmeset's version. + + .DESCRIPTION + A detailed description of the file. + + .PARAMETER TeamName + Name of the Microsoft Teams team + + .PARAMETER TeamsOwner + TeamsOwner of the new Microsoft Teams team + + .PARAMETER privatepublic + Os it a private or Public team? + + .PARAMETER TeamsDescription + The TeamsDescription for the new team + + .PARAMETER ClientId + Azure AD Application (client) ID + + .PARAMETER TenantId + Azure AD Tenant ID + + .PARAMETER ClientSecret + Azure AD secret + + .PARAMETER TenantName + Office 365 Tenant Name (e.g. contoso for https://contoso.sharepoint.com) + + .PARAMETER DocumentLibrary + Document Library Folder, default is /shared documents + + .EXAMPLE + PS C:\> .\ProjectTeamStructure.ps1 -TeamName 'Value1' -TeamsOwner 'Value2' + + .NOTES + Original found in Alexander Holmeset's Blog + My version starts to make it a bit more flexible (e.g. more parameters) + I might update this to be more configurable in the future + + .LINK + https://alexholmeset.blog/2019/05/01/project-team-in-teams-with-folder-structure-in-files-tab/ + + .LINK + https://gist.githubusercontent.com/AlexanderHolmeset/d447cd7c24dd91c3275ad17a5091f0ed/raw/79478f1e789ab36a9236f21a3161685091b12e62/ProjectTeamStructure.ps1 +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param +( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Name of the Microsoft Teams team')] + [Parameter (Mandatory)] + [ValidateNotNullOrEmpty()] + [Alias('Name')] + [String] + $TeamName, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Owner of the new Microsoft Teams team')] + [Parameter (Mandatory)] + [ValidateNotNullOrEmpty()] + [Alias('Owner')] + [String] + $TeamsOwner, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Parameter (Mandatory)] + [ValidateNotNullOrEmpty()] + [String] + $privatepublic = 'Public', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 3)] + [Parameter (Mandatory)] + [Alias('description')] + [String] + $TeamsDescription, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 4)] + [Alias('OAuthClientId')] + [string] + $ClientId, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 5)] + [Alias('OAuthTenantId')] + [string] + $TenantId, + [Parameter(Position = 6)] + [Alias('OAuthClientSecret')] + [string] + $ClientSecret, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 7)] + [string] + $TenantName = 'contoso', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 8)] + [string] + $DocumentLibrary = '/shared documents' +) + +begin +{ + <# + # Azure AD OAuth Application Token for Graph API + # Get OAuth token for a AAD Application (returned as $token) + # Application (client) ID, tenant ID and secret + $ClientId = 'xxxxxxxxxxxxxxxxxxxxxxxx' + $TenantId = 'xxxxxxxxxxxxxxxxxxxxxxxx' + $ClientSecret = 'xxxxxxxxxxxxxxxxxxxxxxxx' + #> +} + +process +{ + # Get the credentials to use + $Cred = (Get-Credential) + + # Connect to Exchange Online + $paramNewPSSession = @{ + ConfigurationName = 'Microsoft.Exchange' + ConnectionUri = 'https://outlook.office365.com/powershell-liveid' + Credential = $Cred + Authentication = 'Basic' + AllowRedirection = $true + } + + $Session = (New-PSSession @paramNewPSSession) + $paramImportPSSession = @{ + Session = $Session + DisableNameChecking = $true + AllowClobber = $true + } + + $null = (Import-PSSession @paramImportPSSession) + + # Connect to Microsoft Teams + $null = (Connect-MicrosoftTeams -Credential $Cred) + + # Contruct URI + $uri = 'https://login.microsoftonline.com/' + $TenantId + '/oauth2/v2.0/token' + + # Construct the JSON Body + $body1 = @{ + client_id = $ClientId + scope = 'https://graph.microsoft.com/.default' + client_secret = $ClientSecret + grant_type = 'client_credentials' + } + + try + { + # Get OAuth 2.0 Token + $paramInvokeWebRequest = @{ + Method = 'Post' + Uri = $uri + ContentType = 'application/x-www-form-urlencoded' + Body = $body1 + ErrorAction = 'Stop' + UseBasicParsing = $true + } + $tokenRequest = (Invoke-WebRequest @paramInvokeWebRequest) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # Extract the Token + $token = (($tokenRequest.Content | ConvertFrom-Json).access_token) + + # Get ID of team requester and set as owner. + $uri = 'https://graph.microsoft.com/beta/users/' + $TeamsOwner + '?$select=id' + $method = 'GET' + + try + { + $paramInvokeWebRequest = @{ + Method = $method + Uri = $uri + ContentType = 'application/json' + Headers = @{ + Authorization = 'Bearer ' + $token + } + ErrorAction = 'Stop' + UseBasicParsing = $true + } + $query = (Invoke-WebRequest @paramInvokeWebRequest) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # Extract the ID + $ownerID = (($query.content | ConvertFrom-Json).id) + + # Specify the URI to call and method + $uri = 'https://graph.microsoft.com/beta/teams' + $method = 'Post' + + # Construct the JSON Body + <# + Please review this defaults, + these settings are applied to the new Microsoft Teams team! + #> + $body = @" +{ +"template@odata.bind": "https://graph.microsoft.com/beta/teamsTemplates/standard", +"displayName": "$TeamName", +"description": "$TeamsDescription", +"channels": [ +{ +"displayName": "01-Management", +"isFavoriteByDefault": true, +"description": "Description" +}, +{ +"displayName": "02-Developement", +"isFavoriteByDefault": true, +"description": "DEscription" +}, +{ +"displayName": "03-Marketing", +"isFavoriteByDefault": true, +"description": "Description" +}, +{ +"displayName": "04-Finance", +"isFavoriteByDefault": true, +"description": "Description" +} +], +"memberSettings": { +"allowCreateUpdateChannels": true, +"allowDeleteChannels": false, +"allowAddRemoveApps": true, +"allowCreateUpdateRemoveTabs": true, +"allowCreateUpdateRemoveConnectors": true +}, +"guestSettings": { +"allowCreateUpdateChannels": false, +"allowDeleteChannels": false +}, +"funSettings": { +"allowGiphy": true, +"giphyContentRating": "Moderate", +"allowStickersAndMemes": true, +"allowCustomMemes": true +}, +"messagingSettings": { +"allowUserEditMessages": true, +"allowUserDeleteMessages": true, +"allowOwnerDeleteMessages": true, +"allowTeamMentions": true, +"allowChannelMentions": true +}, +"visibility": "$Private", +"owners@odata.bind": [ +"https://graph.microsoft.com/beta/users('$ownerID')" +] +} +"@ + + try + { + $paramInvokeWebRequest = @{ + Method = $method + Uri = $uri + ContentType = 'application/json' + Body = $body + Headers = @{ + Authorization = 'Bearer ' + $token + } + ErrorAction = 'Stop' + UseBasicParsing = $true + } + $query = (Invoke-WebRequest @paramInvokeWebRequest) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # Extract the Data + $location = ($query.Headers).Location + $GroupID = $location.Substring(8, 36) + + # Wait a minute to setup the stuff + Start-Sleep -Seconds 60 + + # Get the Mail info about the new team + $TeamSiteName = ((Get-Team -groupid $GroupID).MailNickName) + + # Set some defaults + $SiteURL = 'https://' + $TenantName + '.sharepoint.com/sites/' + $TeamSiteName + $DocumentLibrary = '/shared documents' + + # Channels + # Config Variables + $FolderNames = '01-Management', '02-Developement', '03-Marketing', '04-Finance' + + # Relative URL of the Parent Folder + $RelativeURL = $DocumentLibrary + + try + { + # Connect to PNP Online + $null = (Connect-PnPOnline -Url $SiteURL -Credentials $Cred) + + #sharepoint online create folder powershell + foreach ($Folder in $FolderNames) + { + $paramAddPnPFolder = @{ + Name = $Folder + Folder = $RelativeURL + ErrorAction = 'Stop' + } + $null = (Add-PnPFolder @paramAddPnPFolder) + + Write-Verbose -Message ("New Folder '{0}' Added!" -f $Folder) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # 01-Management + # Config Variables + $FolderNames = 'Meetings', 'Presentations' + $RelativeURL = $DocumentLibrary + '/01-management' #Relative URL of the Parent Folder + + try + { + # Connect to PNP Online + $null = (Connect-PnPOnline -Url $SiteURL -Credentials $Cred) + + # sharepoint online create folder powershell + foreach ($Folder in $FolderNames) + { + $paramAddPnPFolder = @{ + Name = $Folder + Folder = $RelativeURL + ErrorAction = 'Stop' + } + $null = (Add-PnPFolder @paramAddPnPFolder) + + Write-Verbose -Message ("New Folder '{0}' Added!" -f $Folder) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # 02-Developement + # Config Variables + $FolderNames = 'Design', 'Specs', 'Labeling' + + # Relative URL of the Parent Folder + $RelativeURL = $DocumentLibrary + '/02-Developement' + + try + { + # Connect to PNP Online + $null = (Connect-PnPOnline -Url $SiteURL -Credentials $Cred) + + # sharepoint online create folder powershell + foreach ($Folder in $FolderNames) + { + $paramAddPnPFolder = @{ + Name = $Folder + Folder = $RelativeURL + ErrorAction = 'Stop' + } + $null = (Add-PnPFolder @paramAddPnPFolder) + + Write-Verbose -Message ("New Folder '{0}' Added!" -f $Folder) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # Subfolder + $FolderNames = 'Sketches', 'Requirements' + + # Relative URL of the Parent Folder + $RelativeURL = $DocumentLibrary + '/02-Developement/Design' + + try + { + # Connect to PNP Online + $null = (Connect-PnPOnline -Url $SiteURL -Credentials $Cred) + + # sharepoint online create folder powershell + foreach ($Folder in $FolderNames) + { + $paramAddPnPFolder = @{ + Name = $Folder + Folder = $RelativeURL + ErrorAction = 'Stop' + } + $null = (Add-PnPFolder @paramAddPnPFolder) + + Write-Verbose -Message ("New Folder '{0}' Added!" -f $Folder) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # 03-Marketing + # Config Variables + $FolderNames = 'Communication Brief', 'Competitor Review', 'Consumer Insights', 'Product FAQ', 'Product Information', 'Product Strategy' + + # Relative URL of the Parent Folder + $RelativeURL = $DocumentLibrary + '/03-Marketing' + + try + { + # Connect to PNP Online + $null = (Connect-PnPOnline -Url $SiteURL -Credentials $Cred) + + # sharepoint online create folder powershell + foreach ($Folder in $FolderNames) + { + $paramAddPnPFolder = @{ + Name = $Folder + Folder = $RelativeURL + ErrorAction = 'Stop' + } + $null = (Add-PnPFolder @paramAddPnPFolder) + + Write-Verbose -Message ("New Folder '{0}' Added!" -f $Folder) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # 04-Finance + # Config Variables + $FolderNames = 'Budget', 'Presentations' + + # Relative URL of the Parent Folder + $RelativeURL = $DocumentLibrary + '/04-Finance' + + try + { + # Connect to PNP Online + $null = (Connect-PnPOnline -Url $SiteURL -Credentials $Cred) + + # sharepoint online create folder powershell + foreach ($Folder in $FolderNames) + { + $paramAddPnPFolder = @{ + Name = $Folder + Folder = $RelativeURL + ErrorAction = 'Stop' + } + $null = (Add-PnPFolder @paramAddPnPFolder) + + Write-Verbose -Message ("New Folder '{0}' Added!" -f $Folder) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/RemoveWiki.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/RemoveWiki.ps1 new file mode 100644 index 0000000..19645a4 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/RemoveWiki.ps1 @@ -0,0 +1,300 @@ +<# + .SYNOPSIS + Remove the Wiki tab on Microsoft Teams teams + + .DESCRIPTION + Remove the Wiki tab on Microsoft Teams teams + I like Teams, but I never use the Wiki within Teams. + Alexander Holmeset figured out a smart way to get rid of the Wiki tab. + + .PARAMETER ClientId + Azure AD Application (client) ID + + .PARAMETER TenantId + Azure AD Tenant ID + + .PARAMETER ClientSecret + Azure AD secret + + .EXAMPLE + PS C:\> .\RemoveWiki.ps1 -ClientId 'Value1' -TenantId 'Value2' -ClientSecret 'Value3' + + .NOTES + Original found in Alexander Holmeset's Blog + My version starts to make it a bit more flexible (e.g. more parameters) + + .LINK + https://alexholmeset.blog/2019/05/10/remove-the-wiki-tab/ + + .LINK + https://gist.github.com/AlexanderHolmeset/e40c7e9297ae9cc01cb832871a9ff770 +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param +( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Azure AD Application (client) ID')] + [ValidateNotNullOrEmpty()] + [Alias('OAuthClientId')] + [string] + $ClientId, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Azure AD Tenant ID')] + [ValidateNotNullOrEmpty()] + [Alias('OAuthTenantId')] + [string] + $TenantId, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2, + HelpMessage = 'Azure AD secret')] + [ValidateNotNullOrEmpty()] + [Alias('OAuthClientSecret')] + [string] + $ClientSecret +) + +process +{ + # Contruct URI + $uri = 'https://login.microsoftonline.com/' + $TenantId + '/oauth2/v2.0/token' + + try + { + # Construct Body + $body1 = @{ + client_id = $ClientId + scope = 'https://graph.microsoft.com/.default' + client_secret = $ClientSecret + grant_type = 'client_credentials' + } + + # Get OAuth 2.0 Token + $paramInvokeWebRequest = @{ + Method = 'Post' + Uri = $uri + ContentType = 'application/x-www-form-urlencoded' + Body = $body1 + ErrorAction = 'Stop' + UseBasicParsing = $true + } + $tokenRequest = (Invoke-WebRequest @paramInvokeWebRequest) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # Extract the Token + $token = ($tokenRequest.Content | ConvertFrom-Json).access_token + + # Just in case + Write-Verbose -Message $token + + try + { + # URI to call + $uri = 'https://graph.microsoft.com/v1.0/groups' + $paramInvokeRestMethod = @{ + Method = 'GET' + Uri = $uri + ContentType = 'application/json' + Headers = @{ + Authorization = 'Bearer ' + $token + } + ErrorAction = 'Stop' + } + $query = (Invoke-RestMethod @paramInvokeRestMethod) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + # Extract the Value + $groups = $query.value + + foreach ($group in $groups) + { + try + { + if ($group.resourceProvisioningOptions -contains 'Team') + { + # Extract the ID + $id = $group.id + + # Build the URI + $uri2 = 'https://graph.microsoft.com/v1.0/teams/' + $id + '/channels' + + $paramInvokeRestMethod = @{ + Method = 'Get' + Uri = $uri2 + ContentType = 'application/json' + Headers = @{ + Authorization = 'Bearer ' + $token + } + } + $query2 = (Invoke-RestMethod @paramInvokeRestMethod) + + # Extract the Value + $Channels = $query2.value + + foreach ($Channel in $Channels) + { + $id2 = $Channel.id + $uri3 = 'https://graph.microsoft.com/v1.0/teams/' + $id + '/channels/' + $id2 + '/tabs' + $paramInvokeRestMethod = @{ + Method = 'Get' + Uri = $uri3 + ContentType = 'application/json' + Headers = @{ + Authorization = 'Bearer ' + $token + } + } + $query3 = (Invoke-RestMethod @paramInvokeRestMethod) + + # Extract the Value + $tabs = $query3.value + + # Find the Wiki Tab + $WikiTabs = ($tabs | Where-Object -FilterScript { + $_.displayname -eq 'Wiki' + }) + + if ($WikiTabs) + { + foreach ($wikitab in $WikiTabs) + { + # Extract the ID + $wikitabID = $wikitab.id + + # Build the URI + $uri4 = 'https://graph.microsoft.com/v1.0/teams/' + $id + '/channels/' + $id2 + '/tabs/' + $wikitabID + + $paramInvokeRestMethod = @{ + Method = 'DELETE' + Uri = $uri4 + ContentType = 'application/json' + Headers = @{ + Authorization = 'Bearer ' + $token + } + } + $query4 = (Invoke-RestMethod @paramInvokeRestMethod) + + Write-Verbose -Message $query4 + + Write-Output -InputObject 'wikitab removed' + } + } + } + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Continue' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/ReplaceDomainForAllUnifiedGroups.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/ReplaceDomainForAllUnifiedGroups.ps1 new file mode 100644 index 0000000..f298af4 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/ReplaceDomainForAllUnifiedGroups.ps1 @@ -0,0 +1,131 @@ +<# + .SYNOPSIS + Replace the Domain for all UnifiedGroups (and Microsoft Teams) Primary SMTP Address + + .DESCRIPTION + Replace the Domain for all UnifiedGroups (and Microsoft Teams) Primary SMTP Address + + .PARAMETER OldDomain + The old Domain (e.g. contoso.com) + + .PARAMETER NewDomain + The new Domain (e.g. contoso.net) + + .EXAMPLE + PS C:\> .\ReplaceDomainForAllUnifiedGroups.ps1 -OldDomain 'contoso.com' -NewDomain 'contoso.net' + + Replace the Primary SMTP Addresses for all UnifiedGroups (and Microsoft Teams) that are in the domain 'contoso.com' with the someone in the Domain 'contoso.net' + e.g. if an old address was myTeam@contoso.com would end up as myTeam@contoso.new + + .LINK + https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/connect-to-exchange-online-powershell?view=exchange-ps + + .LINK + http://hochwald.net + + .NOTES + Quick and dirty approach, without any real Error handling. + A friend asked me for a solution after a merger to replace all Primary SMTP Addresses and get rid of the old domain (legal requirement in this case) + + You need be be connected to an Exchange Online Session (NOT part of this script). +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess = $true)] +param +( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateNotNullOrEmpty()] + [Alias('DomainToReplace')] + [string] + $OldDomain, + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateNotNullOrEmpty()] + [string] + $NewDomain +) + +begin +{ + $OldMailFilter = ('@' + $OldDomain) + + # Cleanup + $AllUnifiedGroups = $null +} + +process +{ + $AllUnifiedGroups = (Get-UnifiedGroup | Where-Object -FilterScript { + $_.PrimarySmtpAddress -like ('*' + $OldMailFilter) + } | Select-Object -Property Identity, DisplayName, PrimarySmtpAddress) + + if ($AllUnifiedGroups) + { + foreach ($item in $AllUnifiedGroups) + { + if ($item.PrimarySmtpAddress -like ('*' + $OldMailFilter)) + { + $OldMailAddress = $null + $OldMailAddress = (($item).PrimarySmtpAddress) + + $NewMailAddress = $null + $NewMailAddress = ($OldMailAddress.Replace($OldMailFilter, ('@' + $NewDomain))) + Write-Verbose -Message ('Replace: {0} with: {1}' -f $OldMailAddress, $NewMailAddress) + + # Add the new Address + $null = (Set-UnifiedGroup -Identity (($item).Identity) -EmailAddresses: @{ + Add = $NewMailAddress + } -Confirm:$false) + + # Make new Address the primary SMTP address + $null = (Set-UnifiedGroup -Identity (($item).Identity) -PrimarySmtpAddress $NewMailAddress -Confirm:$false) + + # Remove the old SMTP Address + $null = (Set-UnifiedGroup -Identity (($item).Identity) -EmailAddresses: @{ + Remove = $OldMailAddress + } -Confirm:$false) + } + else + { + Write-Warning -Message ('Sorry, the PrimarySmtpAddress of {0} is not in {1}' -f $item.DisplayName, $OldDomain) + } + } + } + else + { + Write-Output -InputObject 'Nothing to do!!!' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Set-QoSForMicrosoftTeams.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Set-QoSForMicrosoftTeams.ps1 new file mode 100644 index 0000000..a461ecc --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Set-QoSForMicrosoftTeams.ps1 @@ -0,0 +1,210 @@ +#requires -Version 3.0 -Modules NetQos -RunAsAdministrator +<# + .SYNOPSIS + Apply QoS Settings for Microsoft Teams + + .DESCRIPTION + Apply Network Quality of Service (QoS) settings for Microsoft Teams. + + .PARAMETER AppPathNameMatchCondition + Specifies the name by which an application is run, such as application.exe or %ProgramFiles%\application.exe application. + + .EXAMPLE + PS C:\> .\Set-QoSForMicrosoftTeams.ps1 + + .EXAMPLE + PS C:\> .\Set-QoSForMicrosoftTeamsRoom.ps1 -AppPathNameMatchCondition 'Teams.exe' + + .NOTES + Changelog: + 1.0.0: Initial Release (Adopted from Set-QoSForMicrosoftTeamsRoomDevices.ps1) + + Version 1.0.0 + + .LINK + Get-NetQosPolicy + + .LINK + New-NetQosPolicy + + .LINK + https://docs.microsoft.com/en-us/microsoftteams/qos-in-teams-clients + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('AppName')] + [string] + $AppPathNameMatchCondition = 'Teams.exe' +) + +begin +{ + Write-Output -InputObject 'Apply Network Quality of Service (QoS) settings for Microsoft Teams' + + #region Defaults + $CNT = 'Continue' + $STP = 'Stop' + $SCT = 'SilentlyContinue' + + [string]$AppSharingPolicy = 'Microsoft Teams AppSharing' + [string]$VideoPolicy = 'Microsoft Teams Video' + [string]$AudioPoliy = 'Microsoft Teams Audio' + #endregion Defaults +} + +process +{ + if ($pscmdlet.ShouldProcess('QoS-Settings', 'Apply')) + { + #region Audio + $paramGetNetQosPolicy = @{ + Name = $AudioPoliy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50000 + IPSrcPortEndMatchCondition = 50019 + DSCPAction = 46 + IPProtocolMatchCondition = 'Both' + Name = $AudioPoliy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $AudioPoliy) + } + } + #endregion Audio + + #region Video + $paramGetNetQosPolicy = @{ + Name = $VideoPolicy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50020 + IPSrcPortEndMatchCondition = 50039 + DSCPAction = 34 + IPProtocolMatchCondition = 'Both' + Name = $VideoPolicy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $VideoPolicy) + } + } + #endregion Video + + #region AppSharing + $paramGetNetQosPolicy = @{ + Name = $AppSharingPolicy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50040 + IPSrcPortEndMatchCondition = 50059 + DSCPAction = 28 + IPProtocolMatchCondition = 'Both' + Name = $AppSharingPolicy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $AppSharingPolicy) + } + } + #endregion AppSharing + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Set-QoSForMicrosoftTeamsRoomDevices.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Set-QoSForMicrosoftTeamsRoomDevices.ps1 new file mode 100644 index 0000000..39990df --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Set-QoSForMicrosoftTeamsRoomDevices.ps1 @@ -0,0 +1,203 @@ +#requires -Version 3.0 -Modules NetQos -RunAsAdministrator +<# + .SYNOPSIS + Apply QoS Settings for Microsoft Teams Room Devices + + .DESCRIPTION + Apply Network Quality of Service (QoS) settings for Microsoft Teams Room Devices. + I use this script to deploy the QoS settings to MTR devices via Intune. + + .PARAMETER AppPathNameMatchCondition + Specifies the name by which an application is run, such as application.exe or %ProgramFiles%\application.exe application. + + .EXAMPLE + PS C:\> .\Set-QoSForMicrosoftTeamsRoomDevices.ps1 + + .EXAMPLE + PS C:\> .\Set-QoSForMicrosoftTeamsRoomDevices.ps1 -AppPathNameMatchCondition 'Teams.exe' + + .NOTES + Idea based on a Twitter chat with @StaleHansen + + Please ensure to check the Ports! + They must match you Teams Admin Centr (TAC) settings. + + .LINK + Get-NetQosPolicy + + .LINK + New-NetQosPolicy + + .LINK + https://docs.microsoft.com/en-us/microsoftteams/qos-in-teams-clients + + .LINK + https://twitter.com/StaleHansen/status/1294341225647083522 +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('AppName')] + [string] + $AppPathNameMatchCondition = $null +) + +begin +{ + $AppSharingPolicy = 'MTR AppSharing' + $VideoPolicy = 'MTR Video' + $AudioPoliy = 'MTR Audio' +} + +process +{ + if ($pscmdlet.ShouldProcess('QoS-Settings', 'Apply')) + { + #region Audio + $paramGetNetQosPolicy = @{ + Name = $AudioPoliy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50000 + IPSrcPortEndMatchCondition = 50019 + DSCPAction = 46 + IPProtocolMatchCondition = 'Both' + Name = $AudioPoliy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $AudioPoliy) + } + } + #endregion Audio + + #region Video + $paramGetNetQosPolicy = @{ + Name = $VideoPolicy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50020 + IPSrcPortEndMatchCondition = 50039 + DSCPAction = 34 + IPProtocolMatchCondition = 'Both' + Name = $VideoPolicy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $VideoPolicy) + } + } + #endregion Video + + #region AppSharing + $paramGetNetQosPolicy = @{ + Name = $AppSharingPolicy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50040 + IPSrcPortEndMatchCondition = 50059 + DSCPAction = 28 + IPProtocolMatchCondition = 'Both' + Name = $AppSharingPolicy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $AppSharingPolicy) + } + } + #endregion AppSharing + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/SetupTeamsRoom.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/SetupTeamsRoom.ps1 new file mode 100644 index 0000000..2c4a958 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/SetupTeamsRoom.ps1 @@ -0,0 +1,128 @@ +<# + .SYNOPSIS + Create a Microsoft Teams Room Device in Office 365 + + .DESCRIPTION + Create and setup a Microsoft Teams Room Device in Microsoft Office 365 + + .NOTES + Review the variable here. + + You must be connected to the following Services: + - Exchange Online + - MSOL (Not AzureAD!) + - Skype for Business Online (Not Teams!) + + .LINK + https://hochwald.net/microsoft-teams-room-device-1-2/ + + .LINK + https://hochwald.net/microsoft-teams-room-device-2-2/ +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +# Display Name of the Room +$RoomName = 'Your-Teams-Room' + +# Alias of the Room (For the UPN, SMTP, and SIP Address) +$RoomAlias = 'YourTeamsRoom' + +# Keep this safe +$RoomPassword = 'YourSuperSecretRoomPassword' +<# + At the moment, the password for a room/resource will never expire! + So keep this in a safe place. And there is no second factor (MFA). +#> + +# The Domain for the UPN, and the SMTP address +$RoomDomain = 'contoso.com' + +# The Response text for meeting requests +$RoomAdditionalResponse = 'This is a Microsoft Teams Team Room' +<# + Basic HTML is supported here! + This text will be in the meeting respoinse mail, so use it as a info or teaser +#> + +# The ALIAS of the license to apply. +# In this case it is the MEETING_ROOM License in the tenant with the name contoso +$RoomLicence = 'contoso:MEETING_ROOM' +<# + The license must be availible (Buy it before create the room) +#> + +# We need one User that we use to find the SIP Registrar Pool (For Skype for Business and Teams SIP handling) +$CsOnlineUser = 'john.doe' + +#region AutomatedStrings +# Build some strings +$RoomUserPrincipalName = ($RoomAlias + '@' + $RoomDomain) +$CsOnlineUserTemplate = ($CsOnlineUser + '@' + $RoomDomain) +<# + I use the same domain for the UPN and the SMTP/SIP address, + and I highly recommend you to do the same! +#> +#endregion AutomatedStrings + +#region NewMailbox +# Create the Mailbox +$paramNewMailbox = @{ + Name = $RoomName + Alias = $RoomAlias + Room = $true + EnableRoomMailboxAccount = $true + MicrosoftOnlineServicesID = $RoomUserPrincipalName + RoomMailboxPassword = (ConvertTo-SecureString -String $RoomPassword -AsPlainText -Force) +} +New-Mailbox @paramNewMailbox +#endregion NewMailbox + +#region SetCalendarProcessing +# Tweak Calendar settings +$paramSetCalendarProcessing = @{ + Identity = $RoomName + AutomateProcessing = 'AutoAccept' + AddOrganizerToSubject = $false + DeleteComments = $false + DeleteSubject = $false + RemovePrivateProperty = $false + AddAdditionalResponse = $true + AdditionalResponse = $RoomAdditionalResponse +} +Set-CalendarProcessing @paramSetCalendarProcessing +<# + Please review the parameters above! + They might not match your taste or requirements + You can add more: Use 'Get-Help Set-CalendarProcessing -details' to see all supported paramaters +#> +#endregion SetCalendarProcessing + +#region SetMsolUser +# Usage location and password tweak +$paramSetMsolUser = @{ + UserPrincipalName = $RoomUserPrincipalName + PasswordNeverExpires = $true + UsageLocation = 'DE' +} +Set-MsolUser @paramSetMsolUser +#endregion SetMsolUser + +#region SetMsolUserLicense +# Apply the license +$paramSetMsolUserLicense = @{ + UserPrincipalName = $RoomUserPrincipalName + AddLicenses = $RoomLicence +} +Set-MsolUserLicense @paramSetMsolUserLicense +#endregion SetMsolUserLicense + +#region EnableCsMeetingRoom +# Enable SIP (Skype for Business/Teams) +$paramEnableCsMeetingRoom = @{ + Identity = $RoomUserPrincipalName + RegistrarPool = (Get-CsOnlineUser -Identity $CsOnlineUserTemplate | Select-Object -ExpandProperty RegistrarPool) + SipAddressType = 'EmailAddress' +} +Enable-CsMeetingRoom @paramEnableCsMeetingRoom +#endregion EnableCsMeetingRoom diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/Update-UnifiedGroupsToTeams.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/Update-UnifiedGroupsToTeams.ps1 new file mode 100644 index 0000000..bd39c32 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/Update-UnifiedGroupsToTeams.ps1 @@ -0,0 +1,227 @@ +function Update-UnifiedGroupsToTeams +{ + <# + .SYNOPSIS + Converts all Microsoft Office 365 Groups into a new Microsoft Teams Team + + .DESCRIPTION + Converts all Microsoft Office 365 Groups into a new Microsoft Teams Team + Microsoft Office 365 Groups are also known as Unified Office 365 Groups + + .PARAMETER ReportOnly + Shows a list of Microsoft Office 365 Groups that would be migrated to a new Microsoft Teams Team. + This is a DryRun only! + + .EXAMPLE + PS C:\> Update-UnifiedGroupsToTeams + + Converting all Microsoft Office 365 Groups into a new Microsoft Teams Team + + .EXAMPLE + PS C:\> Update-UnifiedGroupsToTeams -ReportOnly + + Do a DryRun (Just get a List of Unified Groups that do NOT have a Microsoft Teams Team) + + .EXAMPLE + PS C:\> Compare-Object -ReferenceObject ((Get-Team | Select-Object -ExpandProperty GroupId)) -DifferenceObject ((Get-UnifiedGroup -ResultSize Unlimited | Select-Object -ExpandProperty ExternalDirectoryObjectId)) -PassThru + + Get a short difference list (this function is not required to do so) + + .NOTES + Releasenotes: + 1.0.1 2019-04-21: Add a bit more error handling + 1.0.0 2018-04-14: Internal Release + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + The script depends on Microsoft's Version 0.9.6, or newer, of the MicrosoftTeams PowerShell Module + + Install it with PowerShellGet: + PS C:\> Install-Module MicrosoftTeams + + You need to be connected to Office 365 (Exchange Online). The function will check that. + + .LINK + https://www.powershellgallery.com/packages/MicrosoftTeams/0.9.6 + + .LINK + https://aka.ms/InstallModule + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [Alias('DryRun')] + [switch] + $ReportOnly + ) + + begin + { + #region Defaults + $CNT = 'Continue' + $STP = 'Stop' + #endregion Defaults + + try + { + #region ConnectionCheck + if (-not (Get-Command -Name Get-UnifiedGroup -ErrorAction SilentlyContinue)) + { + $ErrorParameter = @{ + Message = 'Please connect to Office 365/Exchange Online before using this function!' + Category = 'ResourceUnavailable' + RecommendedAction = 'Connect to Office 365/Exchange Online before using this function' + ErrorAction = $STP + } + Write-Error @ErrorParameter + } + #endregion ConnectionCheck + + #region GetUnifiedGroups + $GetUnifiedGroupParameter = @{ + ResultSize = 'Unlimited' + ErrorAction = $STP + WarningAction = $CNT + } + $AllOffice365UnifiedGroups = (Get-UnifiedGroup @GetUnifiedGroupParameter | Select-Object -Property DisplayName, ExternalDirectoryObjectId) + #endregion GetUnifiedGroups + + #region GetMicrosoftTeams + $GetTeamParameter = @{ + ErrorAction = $STP + WarningAction = $CNT + } + $AllMicrosoftTeams = (Get-Team @GetTeamParameter | Select-Object -ExpandProperty GroupId) + #endregion GetMicrosoftTeams + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Dump the FULL error record + Write-Warning -Message ($info | Out-String) + + Write-Error -Message $info.Exception -Exception $info.Exception -ErrorAction $STP + + break + } + } + + process + { + if ($AllOffice365UnifiedGroups) + { + #region Loop + foreach ($Office365UnifiedGroup in $AllOffice365UnifiedGroups) + { + if (-not ($AllMicrosoftTeams -match $Office365UnifiedGroup.ExternalDirectoryObjectId)) + { + if ($ReportOnly) + { + #region ReportOnly + $SingleOffice365UnifiedGroup = $Office365UnifiedGroup.DisplayName + Write-Output -InputObject ('Microsoft Teams for Unified Group {0} is missing' -f $SingleOffice365UnifiedGroup) + #endregion ReportOnly + } + else + { + #region CreateMissingTeam + Write-Verbose -Message ('Create Microsoft Teams Team for Unified Group {0}' -f $SingleOffice365UnifiedGroup) + + try + { + $NewTeamParameter = @{ + Group = $Office365UnifiedGroup + ErrorAction = $STP + WarningAction = $CNT + } + $NewTeam = (New-Team @NewTeamParameter) + + Write-Debug -Message $NewTeam + + Write-Verbose -Message ('Created Microsoft Teams Team for Unified Group {0}' -f $SingleOffice365UnifiedGroup) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $TheException = $info.Exception + + Write-Warning -Message ('Microsoft Teams creation for {0} failed with {1} ' -f $SingleOffice365UnifiedGroup, $TheException) + + # Dump the FULL error record + Write-Verbose -Message ($info | Out-String) + } + #endregion CreateMissingTeam + } + } + } + #endregion Loop + } + else + { + Write-Warning -Message 'No Unified Groups found in your Tenant...' + } + } + + end + { + Write-Verbose -Message 'Done.' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/MicrosoftTeams/enable-AttendanceListMicrosoftTeams.ps1 b/Powershell/PowerShell-collection/MicrosoftTeams/enable-AttendanceListMicrosoftTeams.ps1 new file mode 100644 index 0000000..fb6e356 --- /dev/null +++ b/Powershell/PowerShell-collection/MicrosoftTeams/enable-AttendanceListMicrosoftTeams.ps1 @@ -0,0 +1,23 @@ +# Use the latest Microsoft Teams PowerShell Module to connect +# Not the Skype for Business Online Module (outdated) + +# Get all Teams Meeting Policies +Get-CsTeamsMeetingPolicy | Select-Object -ExpandProperty Identity + +# Get all Teams Meeting Policies, exclude all TAG Policies (You can not modify them with Get-CsTeamsMeetingPolicy) +Get-CsTeamsMeetingPolicy | Where-Object -FilterScript { + $_.Identity -notlike 'Tag:*' +} | Select-Object -ExpandProperty Identity + +# Modify the Global Policy +Set-CsTeamsMeetingPolicy -Identity Global -AllowEngagementReport Enabled + +# Modify any Policy by name +Set-CsTeamsMeetingPolicy -Identity 'Meetings' | Set-CsTeamsMeetingPolicy -AllowEngagementReport Enabled + +# Modify all Policies (exclude the TAG Policies, because you can not modify them with Get-CsTeamsMeetingPolicy) +Get-CsTeamsMeetingPolicy | Where-Object -FilterScript { + $_.Identity -notlike 'Tag:*' +} | ForEach-Object -Process { + Set-CsTeamsMeetingPolicy -Identity $_.Identity -AllowEngagementReport Enabled -ErrorAction Continue +} diff --git a/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Bootstrap-MicrosoftDefenderConfiguration.csv b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Bootstrap-MicrosoftDefenderConfiguration.csv new file mode 100644 index 0000000..82c052a --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Bootstrap-MicrosoftDefenderConfiguration.csv @@ -0,0 +1,16 @@ +RuleID,RuleDescription,RuleAction +75668C1F-73B5-4CF0-BB93-3ECF5CB7CC84, Block Office applications from injecting into other processes, Enabled +3B576869-A4EC-4529-8536-B80A7769E899, Block Office applications from creating executable content, Enabled +D4F940AB-401B-4EfC-AADC-AD5F3C50688A, Block Office applications from creating child processes, Enabled +D3E037E1-3EB8-44C8-A917-57927947596D, Impede JavaScript and VBScript to launch executables, Enabled +5BEB7EFE-FD9A-4556-801D-275E5FFC04CC, Block execution of potentially obfuscated script, Enabled +BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550, Block executable content from email client and webmail, Enabled +92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B, Block Win32 imports from Macro code in Office, Enabled +c1db55ab-c21a-4637-bb3f-a12568109d35, Use advanced protection against ransomware, Enabled +9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2, Block credential stealing from the Windows local security authority subsystem (lsass.exe), Enabled +d1e49aac-8f56-4280-b9ba-993a6d77406c, Block process creations originating from PSExec and WMI commands, Enabled +b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4, Block untrusted and unsigned processes that run from USB, Enabled +26190899-1602-49e8-8b27-eb1d0a1ce869, Block Office communication applications from creating child processes, AuditMode +7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c, Block Adobe Reader from creating child processes, Enabled +e6db77e5-3df2-4cf1-b95a-636979351e5b, Block persistence through WMI event subscription, Enabled +01443614-cd74-433a-b99e-2ecdc07bfc25, Block executable files from running unless they meet a prevalence age or trusted list criteria, AuditMode \ No newline at end of file diff --git a/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Bootstrap-MicrosoftDefenderConfiguration.ps1 b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Bootstrap-MicrosoftDefenderConfiguration.ps1 new file mode 100644 index 0000000..4d55e2b --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Bootstrap-MicrosoftDefenderConfiguration.ps1 @@ -0,0 +1,676 @@ +#requires -Version 3.0 -Modules ConfigDefender, NetSecurity + +<# + .SYNOPSIS + Bootstrap Microsoft Defender configuration + + .DESCRIPTION + Bootstrap Microsoft Defender configuration, optimize and tweak Windows 10 protection and security + + .PARAMETER CsvPath + The CSV with the configuration. + This is optional. Defaults are in the Script. + + .PARAMETER Force + Enforce to apply the customize attack surface reduction rules + + .EXAMPLE + PS C:\> .\Bootstrap-MicrosoftDefenderConfiguration.ps1 + + Bootstrap Microsoft Defender configuration, optimize and tweak Windows 10 Protection + + .EXAMPLE + PS C:\> .\Bootstrap-MicrosoftDefenderConfiguration.ps1 -Verbose -Force + + Bootstrap Microsoft Defender configuration, optimize and tweak Windows 10 Protection + + .EXAMPLE + PS C:\> .\Bootstrap-MicrosoftDefenderConfiguration.ps1 -Verbose + + Bootstrap Microsoft Defender configuration, optimize and tweak Windows 10 Protection + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/index?view=win10-ps + + .LINK + https://github.com/jhochwald/PowerShell-collection/blob/master/Misc/Optimize-MicrosoftDefenderExclusions.ps1 + + .LINK + https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/enable-exploit-protection + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=win10-ps + + .LINK + https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/customize-attack-surface-reduction + + .LINK + https://support.microsoft.com/en-us/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni + + .LINK + https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-antivirus/enable-cloud-protection-windows-defender-antivirus + + .LINK + https://demo.wd.microsoft.com/?ocid=cx-wddocs-testground + + .NOTES + Please review the settings, please tweak the rules file (or modify the default rule set here) + + You need to run this in an elevated PowerShell! + + I use this during the bootstrap process of Windows systems. + Most of the settings here is also enforced by some of our Group Policies and we also have a lot of it configured via MDM CSPs (InTune). + + This script is only a quick hack to harden (and secure) any new system, even if it is not managed afterwords. +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('RulesCsv')] + [string] + $CsvPath = '.\Bootstrap-MicrosoftDefenderConfiguration.csv', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('EnforceRule')] + [switch] + $Force = $null +) + +begin +{ + # Create a new Mail Object + $AttackSurfaceReductionRuleList = @() + + #region CsvHandler + if (Test-Path -Path $CsvPath -ErrorAction SilentlyContinue) + { + #region ImportCsv + Write-Verbose -Message ('Import the attack surface reduction settings from ' + $CsvPath) + $AttackSurfaceReductionRuleList = (Import-Csv -Path $CsvPath -Delimiter ',' -Encoding UTF8) + #endregion ImportCsv + } + else + { + #region DefaultCsv + Write-Verbose -Message 'Use the attack surface reduction default settings' + + # Create a virtual CSV File (Quick hack: To keep it plain and simple to maintain) + $RuleDefaults = 'RuleID,RuleDescription,RuleAction + 75668C1F-73B5-4CF0-BB93-3ECF5CB7CC84, Block Office applications from injecting into other processes, Enabled + 3B576869-A4EC-4529-8536-B80A7769E899, Block Office applications from creating executable content, Enabled + D4F940AB-401B-4EfC-AADC-AD5F3C50688A, Block Office applications from creating child processes, Enabled + D3E037E1-3EB8-44C8-A917-57927947596D, Impede JavaScript and VBScript to launch executable, Enabled + 5BEB7EFE-FD9A-4556-801D-275E5FFC04CC, Block execution of potentially obfuscated script, Enabled + BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550, Block executable content from email client and webmail, Enabled + 92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B, Block Win32 imports from Macro code in Office, Enabled + c1db55ab-c21a-4637-bb3f-a12568109d35, Use advanced protection against ransomware, Enabled + 9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2, Block credential stealing from the Windows local security authority subsystem (lsass.exe), Enabled + d1e49aac-8f56-4280-b9ba-993a6d77406c, Block process creations originating from PSExec and WMI commands, Enabled + b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4, Block untrusted and unsigned processes that run from USB, Enabled + 26190899-1602-49e8-8b27-eb1d0a1ce869, Block Office communication applications from creating child processes, AuditMode + 7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c, Block Adobe Reader from creating child processes, Enabled + e6db77e5-3df2-4cf1-b95a-636979351e5b, Block persistence through WMI event subscription, Enabled + 01443614-cd74-433a-b99e-2ecdc07bfc25, Block executable files from running unless they meet a prevalence age or trusted list criteria, AuditMode' + + # Import the virtual CSV File + $AttackSurfaceReductionRuleList = (ConvertFrom-Csv -InputObject $RuleDefaults -Delimiter ',') + #endregion DefaultCsv + } + #endregion CsvHandler +} + +process +{ + #region SetMpPreference + #region EnableNetworkProtection + Write-Verbose -Message 'Network protection helps to prevent employees from using any application to access dangerous domains that may host phishing scams, exploits, and other malicious content on the Internet' + $null = (Set-MpPreference -EnableNetworkProtection Enabled -Force -ErrorAction Continue) + #endregion EnableNetworkProtection + + #region EnableControlledFolderAccess + Write-Verbose -Message 'Controlled folder access helps you protect valuable data from malicious apps and threats, such as ransomware' + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction Continue) + #endregion EnableControlledFolderAccess + + #region SignatureScheduleDay + Write-Verbose -Message 'Specifies the day of the week on which to check for definition updates' + $null = (Set-MpPreference -SignatureScheduleDay Everyday -Force -ErrorAction Continue) + #endregion SignatureScheduleDay + + #region SignatureScheduleTime + Write-Verbose -Message 'Specifies the time of day, as the number of minutes after midnight, to check for definition updates' + $null = (Set-MpPreference -SignatureScheduleTime 320 -Force -ErrorAction Continue) + #endregion SignatureScheduleTime + + #region DisableArchiveScanning + Write-Verbose -Message 'Indicates whether to scan archive files for malicious and unwanted software' + $null = (Set-MpPreference -DisableArchiveScanning $true -Force -ErrorAction Continue) + #endregion DisableArchiveScanning + + #region DisableAutoExclusions + Write-Verbose -Message 'Indicates whether to disable the Automatic Exclusions feature for the server' + $null = (Set-MpPreference -DisableAutoExclusions $false -Force -ErrorAction Continue) + #endregion DisableAutoExclusions + + #region DisableBehaviorMonitoring + Write-Verbose -Message 'Indicates whether to enable behavior monitoring' + $null = (Set-MpPreference -DisableBehaviorMonitoring $true -Force -ErrorAction Continue) + #endregion DisableBehaviorMonitoring + + #region DisableBlockAtFirstSeen + Write-Verbose -Message 'Indicates whether to enable block at first seen' + $null = (Set-MpPreference -DisableBlockAtFirstSeen $true -Force -ErrorAction Continue) + #endregion DisableBlockAtFirstSeen + + #region DisableCatchupFullScan + Write-Verbose -Message 'Indicates whether Windows Defender runs catch-up scans for scheduled full scans' + $null = (Set-MpPreference -DisableCatchupFullScan $true -Force -ErrorAction Continue) + #endregion DisableCatchupFullScan + + #region DisableCatchupQuickScan + Write-Verbose -Message 'Indicates whether Windows Defender runs catch-up scans for scheduled quick scans' + $null = (Set-MpPreference -DisableCatchupQuickScan $true -Force -ErrorAction Continue) + #endregion DisableCatchupQuickScan + + #region DisableEmailScanning + Write-Verbose -Message 'Indicates whether Windows Defender parses the mailbox and mail files, according to their specific format, in order to analyze mail bodies and attachments' + $null = (Set-MpPreference -DisableEmailScanning $false -Force -ErrorAction Continue) + #endregion DisableEmailScanning + + #region DisableIOAVProtection + Write-Verbose -Message 'Indicates whether Windows Defender scans all downloaded files and attachments (e.g. Downloads)' + $null = (Set-MpPreference -DisableIOAVProtection $true -Force -ErrorAction Continue) + #endregion DisableIOAVProtection + + #region DisableIntrusionPreventionSystem + Write-Verbose -Message 'Indicates whether to configure network protection against exploitation of known vulnerabilities' + $null = (Set-MpPreference -DisableIntrusionPreventionSystem $false -Force -ErrorAction Continue) + #endregion DisableIntrusionPreventionSystem + + #region DisablePrivacyMode + Write-Verbose -Message 'Indicates whether to disable privacy mode. Privacy mode prevents users, other than administrators, from displaying threat history' + $null = (Set-MpPreference -DisablePrivacyMode $false -Force -ErrorAction Continue) + #endregion DisablePrivacyMode + + #region DisableRealtimeMonitoring + Write-Verbose -Message 'Indicates whether to use real-time protection' + $null = (Set-MpPreference -DisableRealtimeMonitoring $false -Force -ErrorAction Continue) + #endregion DisableRealtimeMonitoring + + #region CheckForSignaturesBeforeRunningScan + Write-Verbose -Message 'Enable checking signatures before scanning' + $null = (Set-MpPreference -CheckForSignaturesBeforeRunningScan 1 -Force -ErrorAction Continue) + #endregion CheckForSignaturesBeforeRunningScan + + #region DisableRemovableDriveScanning + Write-Verbose -Message 'Indicates whether to scan for malicious and unwanted software in removable drives, such as flash drives, during a full scan' + $null = (Set-MpPreference -DisableRemovableDriveScanning $true -Force -ErrorAction Continue) + #endregion DisableRemovableDriveScanning + + #region DisableRestorePoint + Write-Verbose -Message 'Indicates whether to disable scanning of restore points' + $null = (Set-MpPreference -DisableRestorePoint $true -Force -ErrorAction Continue) + #endregion DisableRestorePoint + + #region DisableScanningMappedNetworkDrivesForFullScan + Write-Verbose -Message 'Indicates whether to scan mapped network drives' + $null = (Set-MpPreference -DisableScanningMappedNetworkDrivesForFullScan $true -Force -ErrorAction Continue) + #endregion DisableScanningMappedNetworkDrivesForFullScan + + #region DisableScanningNetworkFiles + Write-Verbose -Message 'Indicates whether to scan for network files' + $null = (Set-MpPreference -DisableScanningNetworkFiles $false -Force -ErrorAction Continue) + #endregion DisableScanningNetworkFiles + + #region DisableScriptScanning + Write-Verbose -Message 'Specifies whether to disable the scanning of scripts during malware scans' + $null = (Set-MpPreference -DisableScriptScanning $false -Force -ErrorAction Continue) + #endregion DisableScriptScanning + + #region HighThreatDefaultAction + Write-Verbose -Message 'Specifies which automatic remediation action to take for a high level threat' + $null = (Set-MpPreference -HighThreatDefaultAction Quarantine -Force -ErrorAction Continue) + #endregion HighThreatDefaultAction + + #region LowThreatDefaultAction + Write-Verbose -Message 'Specifies which automatic remediation action to take for a low level threat' + $null = (Set-MpPreference -LowThreatDefaultAction Block -Force -ErrorAction Continue) + #endregion LowThreatDefaultAction + + #region ModerateThreatDefaultAction + Write-Verbose -Message 'Specifies which automatic remediation action to take for a moderate level threat' + $null = (Set-MpPreference -ModerateThreatDefaultAction Quarantine -Force -ErrorAction Continue) + #endregion ModerateThreatDefaultAction + + #region PUAProtection + Write-Verbose -Message 'Disable PUA Protection' + $null = (Set-MpPreference -PUAProtection Enabled -Force -ErrorAction Continue) + #endregion PUAProtection + + #region QuarantinePurgeItemsAfterDelay + Write-Verbose -Message 'Specifies the number of days to keep items in the Quarantine folder' + $null = (Set-MpPreference -QuarantinePurgeItemsAfterDelay 30 -Force -ErrorAction Continue) + #endregion QuarantinePurgeItemsAfterDelay + + #region RandomizeScheduleTaskTimes + Write-Verbose -Message 'Indicates whether to select a random time for the scheduled start and scheduled update for definitions' + $null = (Set-MpPreference -RandomizeScheduleTaskTimes $true -Force -ErrorAction Continue) + #endregion RandomizeScheduleTaskTimes + + #region RealTimeScanDirection + Write-Verbose -Message 'Specifies scanning configuration for incoming and outgoing files on NTFS volumes' + $null = (Set-MpPreference -RealTimeScanDirection 0 -Force -ErrorAction Continue) + #endregion RealTimeScanDirection + + #region RemediationScheduleDay + Write-Verbose -Message 'Specifies the day of the week on which to perform a scheduled full scan in order to complete remediation' + $null = (Set-MpPreference -RemediationScheduleDay Everyday -Force -ErrorAction Continue) + #endregion + + #region RemediationScheduleTime + Write-Verbose -Message 'Specifies the time of day, as the number of minutes after midnight, to perform a scheduled scan' + $null = (Set-MpPreference -RemediationScheduleTime 120 -Force -ErrorAction Continue) + #endregion RemediationScheduleDay + + #region ReportingAdditionalActionTimeOut + Write-Verbose -Message 'Specifies the number of minutes before a detection in the additional action state changes to the cleared state' + $null = (Set-MpPreference -ReportingAdditionalActionTimeOut 10080 -Force -ErrorAction Continue) + #endregion ReportingAdditionalActionTimeOut + + #region ReportingCriticalFailureTimeOut + Write-Verbose -Message 'Specifies the number of minutes before a detection in the critically failed state changes to either the additional action state or the cleared state' + $null = (Set-MpPreference -ReportingCriticalFailureTimeOut 10080 -Force -ErrorAction Continue) + #endregion ReportingCriticalFailureTimeOut + + #region ReportingNonCriticalTimeOut + Write-Verbose -Message 'Specifies the number of minutes before a detection in the non-critically failed state changes to the cleared state' + $null = (Set-MpPreference -ReportingNonCriticalTimeOut 11440 -Force -ErrorAction Continue) + #endregion ReportingNonCriticalTimeOut + + #region ScanAvgCPULoadFactor + Write-Verbose -Message 'Specifies the maximum percentage CPU usage for a scan' + $null = (Set-MpPreference -ScanAvgCPULoadFactor 50 -Force -ErrorAction Continue) + #endregion ScanAvgCPULoadFactor + + #region ScanOnlyIfIdleEnabled + Write-Verbose -Message 'Indicates whether to start scheduled scans only when the computer is not in use' + $null = (Set-MpPreference -ScanOnlyIfIdleEnabled $true -Force -ErrorAction Continue) + #endregion ScanOnlyIfIdleEnabled + + #region ScanParameters + Write-Verbose -Message 'Specifies the scan type to use during a scheduled scan' + $null = (Set-MpPreference -ScanParameters 1 -Force -ErrorAction Continue) + #endregion ScanParameters + + #region ScanPurgeItemsAfterDelay + Write-Verbose -Message 'Specifies the number of days to keep items in the scan history folder' + $null = (Set-MpPreference -ScanPurgeItemsAfterDelay 15 -Force -ErrorAction Continue) + #endregion ScanPurgeItemsAfterDelay + + #region ScanScheduleDay + Write-Verbose -Message 'Specifies the day of the week on which to perform a scheduled scan' + $null = (Set-MpPreference -ScanScheduleDay Everyday -Force -ErrorAction Continue) + #endregion ScanScheduleDay + + #region ScanScheduleQuickScanTime + Write-Verbose -Message 'Specifies the time of day, as the number of minutes after midnight, to perform a scheduled quick scan' + $null = (Set-MpPreference -ScanScheduleQuickScanTime 0 -Force -ErrorAction Continue) + #endregion ScanScheduleQuickScanTime + + #region ScanScheduleTime + Write-Verbose -Message 'Specifies the time of day, as the number of minutes after midnight, to perform a scheduled scan' + $null = (Set-MpPreference -ScanScheduleTime 120 -Force -ErrorAction Continue) + #endregion ScanScheduleTime + + #region SevereThreatDefaultAction + Write-Verbose -Message 'Specifies which automatic remediation action to take for a severe level threat' + $null = (Set-MpPreference -SevereThreatDefaultAction Quarantine -Force -ErrorAction Continue) + #endregion SevereThreatDefaultAction + + #region SignatureAuGracePeriod + Write-Verbose -Message 'Specifies a grace period, in minutes, for the definition' + $null = (Set-MpPreference -SignatureAuGracePeriod 0 -Force -ErrorAction Continue) + #endregion SignatureAuGracePeriod + + #region SignatureDisableUpdateOnStartupWithoutEngine + Write-Verbose -Message 'Indicates whether to initiate definition updates even if no antimalware engine is present' + $null = (Set-MpPreference -SignatureDisableUpdateOnStartupWithoutEngine $false -Force -ErrorAction Continue) + #endregion SignatureDisableUpdateOnStartupWithoutEngine + + #region SignatureFirstAuGracePeriod + Write-Verbose -Message 'Specifies a grace period, in minutes, for the definition. If a definition successfully updates within this period, Windows Defender abandons any service initiated updates' + $null = (Set-MpPreference -SignatureFirstAuGracePeriod 120 -Force -ErrorAction Continue) + #endregion SignatureFirstAuGracePeriod + + #region SignatureScheduleDay + Write-Verbose -Message 'Specifies the day of the week on which to check for definition updates' + $null = (Set-MpPreference -SignatureScheduleDay Everyday -Force -ErrorAction Continue) + #endregion SignatureScheduleDay + + #region SignatureScheduleTime + Write-Verbose -Message 'Specifies the time of day, as the number of minutes after midnight, to check for definition updates' + $null = (Set-MpPreference -SignatureScheduleTime 165 -Force -ErrorAction Continue) + #endregion SignatureScheduleTime + + #region SignatureUpdateCatchupInterval + Write-Verbose -Message 'Specifies the number of days after which Windows Defender requires a catch-up definition update' + $null = (Set-MpPreference -SignatureUpdateCatchupInterval 1 -Force -ErrorAction Continue) + #endregion SignatureUpdateCatchupInterval + + #region SignatureUpdateInterval + Write-Verbose -Message 'Specifies the interval, in hours, at which to check for definition updates' + $null = (Set-MpPreference -SignatureUpdateInterval 12 -Force -ErrorAction Continue) + #endregion SignatureUpdateInterval + + #region SubmitSamplesConsent + Write-Verbose -Message 'Specifies how Windows Defender checks for user consent for certain samples' + $null = (Set-MpPreference -SubmitSamplesConsent AlwaysPrompt -Force -ErrorAction Continue) + #endregion SubmitSamplesConsent + + #region MAPSReporting MAPSReporting + Write-Verbose -Message 'Membership in Microsoft Active Protection Service Enable' + $null = (Set-MpPreference -MAPSReporting Advanced -Force -ErrorAction Continue) + #endregion MAPSReporting MAPSReporting + + #region ThrottleLimit + Write-Verbose -Message 'Specifies the maximum number of concurrent operations that can be established to run the cmdlet' + $null = (Set-MpPreference -ThrottleLimit 0 -Force -ErrorAction Continue) + #endregion ThrottleLimit + + #region UILockdown + Write-Verbose -Message 'Indicates whether to disable UI lock down mode' + $null = (Set-MpPreference -UILockdown $false -Force -ErrorAction Continue) + #endregion UILockdown + + #region UnknownThreatDefaultAction + Write-Verbose -Message 'Specifies which automatic remediation action to take for an unknown level threat' + $null = (Set-MpPreference -UnknownThreatDefaultAction Block -Force -ErrorAction Continue) + #endregion UnknownThreatDefaultAction + + #region SignatureFallbackOrder + Write-Verbose -Message 'Specifies the order in which to contact different definition update sources.' + $null = (Set-MpPreference -SignatureFallbackOrder 'MicrosoftUpdateServer | MMPC' -Force -ErrorAction Continue) + #endregion SignatureFallbackOrder + + #region ControlledFolderAccessAllowedApplications + Write-Verbose -Message 'Setup the Controlled Folder Access Allowed Applications' + + # Define a list of Applications to exclude - Fully Qualified + <# + I like to keep this list as short as possible + #> + $NewControlledFolderAccessAllowedApplications = @( + "$env:windir\System32\taskhostw.exe" + ) + + # Create a new Object + $AllControlledFolderAccessAllowedApplications = (New-Object -TypeName System.Collections.Generic.List[System.Object]) + + # Get the existing exclusions + $AllControlledFolderAccessAllowedApplications.Add((Get-MpPreference -ErrorAction SilentlyContinue | Select-Object -ExpandProperty ControlledFolderAccessAllowedApplications)) + + #region NewControlledFolderAccessAllowedApplicationsLoop + foreach ($NewControlledFolderAccessAllowedApplication in $NewControlledFolderAccessAllowedApplications) + { + if ($AllControlledFolderAccessAllowedApplications -notcontains $NewControlledFolderAccessAllowedApplication) + { + Write-Verbose -Message ('Add ' + $NewControlledFolderAccessAllowedApplication + ' to the Controlled Folder Access Allowed Applications list') + + $AllControlledFolderAccessAllowedApplications.Add($NewControlledFolderAccessAllowedApplication) + } + } + #endregion NewControlledFolderAccessAllowedApplicationsLoop + + # Make sure we have nothing doubled + $AllControlledFolderAccessAllowedApplications = ($AllControlledFolderAccessAllowedApplications | Sort-Object -Unique) + + # Apply the new exclusion list. This will replace the complete list. + Write-Verbose -Message 'Apply the new Controlled Folder Access Allowed Applications list' + + $null = (Set-MpPreference -ControlledFolderAccessAllowedApplications $AllControlledFolderAccessAllowedApplications -Force -ErrorAction Continue) + #endregion ControlledFolderAccessAllowedApplications + + #region ExclusionPath + # Define a list of Applications to exclude - Fully Qualified + $NewExclusionPathList = @( + "$env:windir\SoftwareDistribution\DataStore\Datastore.edb", + "$env:windir\SoftwareDistribution\DataStore\Logs\Edb*.jrs", + "$env:windir\SoftwareDistribution\DataStore\Logs\Edb.chk", + "$env:windir\SoftwareDistribution\DataStore\Logs\Tmp.edb", + "$env:windir\Security\Database\*.edb", + "$env:windir\Security\Database\*.sdb", + "$env:windir\Security\Database\*.log", + "$env:windir\Security\Database\*.chk", + "$env:windir\Security\Database\*.jrs", + "$env:windir\Security\Database\*.xml", + "$env:windir\Security\Database\*.csv", + "$env:windir\Security\Database\*.cmtx", + "$env:ProgramData\ntuser.pol", + "$env:windir\System32\GroupPolicy\Machine\Registry.pol", + "$env:windir\System32\GroupPolicy\Machine\Registry.tmp", + "$env:windir\System32\GroupPolicy\User\Registry.pol", + "$env:windir\System32\GroupPolicy\User\Registry.tmp" + ) + + # Create a new Object + $AllExclusionPath = (New-Object -TypeName System.Collections.Generic.List[System.Object]) + + # Get the existing exclusions + $AllExclusionPath.Add((Get-MpPreference -ErrorAction SilentlyContinue | Select-Object -ExpandProperty ExclusionPath)) + + #region NewExclusionPathLoop + foreach ($NewExclusionPath in $NewExclusionPathList) + { + if ($AllExclusionPath -notcontains $NewExclusionPath) + { + Write-Verbose -Message ('Add ' + $NewExclusionPath + ' as path to exclude') + + $AllExclusionPath.Add($NewExclusionPath) + } + } + #endregion NewExclusionPathLoop + + # Make sure we have nothing doubled + $AllExclusionPath = ($AllExclusionPath | Sort-Object -Unique) + + # Apply the new exclusion list. This will replace the complete list. + Write-Verbose -Message 'Apply the new Path to exclude list' + + $null = (Set-MpPreference -ExclusionPath $AllExclusionPath -Force -ErrorAction Continue) + #endregion ExclusionPath + + #region ExclusionProcess + # Define a list of Applications to exclude - Fully Qualified + $NewExclusionProcessList = @( + "$env:windir\System32\svchost.exe", + "$env:windir\System32\wuauclt.exe" + ) + + # Create a new Object + $AllExclusionProcess = (New-Object -TypeName System.Collections.Generic.List[System.Object]) + + # Get the existing exclusions + $AllExclusionProcess.Add((Get-MpPreference -ErrorAction SilentlyContinue | Select-Object -ExpandProperty ExclusionProcess)) + + #region NewExclusionProcessLoop + foreach ($NewExclusionProcess in $NewExclusionProcessList) + { + if ($AllExclusionProcess -notcontains $NewExclusionProcess) + { + Write-Verbose -Message ('Add ' + $NewExclusionProcess + ' as process to exclude') + + $AllExclusionProcess.Add($NewExclusionProcess) + } + } + #endregion NewExclusionProcessLoop + + # Make sure we have nothing doubled + $AllExclusionProcess = ($AllExclusionProcess | Sort-Object -Unique) + + # Apply the new exclusion list. This will replace the complete list. + Write-Verbose -Message 'Apply the new Process to exclude list' + + $null = (Set-MpPreference -ExclusionProcess $AllExclusionProcess -Force -ErrorAction Continue) + #endregion ExclusionProcess + #endregion SetMpPreference + + #region ProcessMitigation + # Local Process Mitigation file + $ProcessMitigationFile = '.\ProcessMitigation.xml' + + # Check if we have a local Process Mitigation file + if (-not (Test-Path -Path $ProcessMitigationFile -ErrorAction SilentlyContinue)) + { + # Where to download the XML File? + $ProcessMitigationUri = 'https://demo.wd.microsoft.com/Content/ProcessMitigation.xml' + + Write-Verbose -Message ('Downloading Process Mitigation file from ' + $ProcessMitigationUri) + + # Download + $paramInvokeWebRequest = @{ + Uri = $ProcessMitigationUri + OutFile = $ProcessMitigationFile + Method = 'Get' + ContentType = 'text/xml' + ErrorAction = 'Continue' + } + $null = (Invoke-WebRequest @paramInvokeWebRequest) + } + + if (Test-Path -Path $ProcessMitigationFile -ErrorAction SilentlyContinue) + { + Write-Verbose -Message 'Enabling Exploit Protection' + + # Apply the File + $null = (Set-ProcessMitigation -PolicyFilePath $ProcessMitigationFile -ErrorAction Continue) + + # Cleanup + $paramRemoveItem = @{ + Path = $ProcessMitigationFile + Force = $true + Confirm = $false + ErrorAction = 'Continue' + } + $null = (Remove-Item @paramRemoveItem) + } + else + { + Write-Warning -Message ('The local Process Mitigation file (' + $ProcessMitigationFile + ') is missing! Not enabling Exploit Protection.') + } + #endregion ProcessMitigation + + #region WindowsDefenderSandbox + Write-Verbose -Message 'Turn on Windows Defender Sandbox' + $null = ([Environment]::SetEnvironmentVariable('MP_FORCE_USE_SANDBOX', 1, 'Machine')) + #endregion WindowsDefenderSandbox + + #region AttackSurfaceReduction + #region GetAttackSurfaceReductionRulesIds + $AttackSurfaceReductionRulesIds = (Get-MpPreference -ErrorAction SilentlyContinue | Select-Object -ExpandProperty AttackSurfaceReductionRules_Ids) + #endregion GetAttackSurfaceReductionRulesIds + + Write-Verbose -Message 'Enabling Attack Surface Reduction rules' + + #region SetMpPreferenceDefaults + $AddMpPreferenceParameters = @{ + ErrorAction = 'Stop' + Force = $true + } + #endregion SetMpPreferenceDefaults + + #region RuleLoop + foreach ($AttackSurfaceReductionRule in $AttackSurfaceReductionRuleList) + { + #region SingleLoop + try + { + if (($Force) -or ($AttackSurfaceReductionRulesIds -notcontains $AttackSurfaceReductionRule.RuleID)) + { + #region AppleTheRuleValue + Write-Verbose -Message ('Set ' + $AttackSurfaceReductionRule.RuleDescription + ' to ' + $AttackSurfaceReductionRule.RuleAction) + + # Add some values + $AddMpPreferenceParameters.AttackSurfaceReductionRules_Ids = $AttackSurfaceReductionRule.RuleID + $AddMpPreferenceParameters.AttackSurfaceReductionRules_Actions = $AttackSurfaceReductionRule.RuleAction + + # Apply the Rule + $null = (Add-MpPreference @AddMpPreferenceParameters) + #endregion AppleTheRuleValue + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message ('Unable to enable to Rule: ' + $AttackSurfaceReductionRule.RuleID + ' (' + $AttackSurfaceReductionRule.RuleDescription + ')') + #endregion ErrorHandler + } + #endregion SingleLoop + } + #endregion RuleLoop + #endregion AttackSurfaceReduction + + #region ReloadRegistry + & "$env:windir\system32\rundll32.exe" USER32.DLL, UpdatePerUserSystemParameters , 1 , True + #endregion ReloadRegistry + + #region EnableFirewall + Write-Verbose -Message 'Enable the Windows Firewall for all Profiles - Set the default to block everything' + $null = (Set-NetFirewallProfile -Profile Domain, Public, Private -Enabled True -DefaultInboundAction Block -LogBlocked True -Confirm:$false -ErrorAction Continue) + #endregion EnableFirewall +} + +end +{ + #region UpdateSignature + Write-Verbose -Message 'Update Defender' + $null = (Update-MpSignature) + #endregion UpdateSignature +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/LICENSE b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Readme.md b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Readme.md new file mode 100644 index 0000000..55ef87d --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Bootstrap-MicrosoftDefenderConfiguration/Readme.md @@ -0,0 +1,476 @@ +# Bootstrap Microsoft Defender configuration + +Bootstrap Microsoft Defender configuration, optimize and tweak Windows 10 protection and security + +## What it does + +Several Microsoft Defender settings are configured. + +### EnableNetworkProtection + +Network protection helps to prevent employees from using any application to access dangerous domains that may host phishing scams, exploits, and other malicious content on the Internet + +Set to: `Enabled` + +### EnableControlledFolderAccess + +Controlled folder access helps you protect valuable data from malicious apps and threats, such as ransomware + +Set to: `Enabled` + +### SignatureScheduleDay + +Specifies the day of the week on which to check for definition updates. + +Set to: `Everyday` + +### SignatureScheduleTime + +Specifies the time of day, as the number of minutes after midnight, to check for definition updates + +Set to: `320` + +### DisableArchiveScanning + +Indicates whether to scan archive files for malicious and unwanted software + +Set to: `true` + +### DisableAutoExclusions + +Indicates whether to disable the Automatic Exclusions feature for the server + +Set to: `false` + +### DisableBehaviorMonitoring + +Indicates whether to enable behavior monitoring + +Set to: `true` + +Something I enable on a few systems only. + +### DisableBlockAtFirstSeen + +Indicates whether to enable block at first seen + +Set to: `true` + +### DisableCatchupFullScan + +Indicates whether Windows Defender runs catch-up scans for scheduled full scans + +Set to: `true` + +### DisableCatchupQuickScan + +Indicates whether Windows Defender runs catch-up scans for scheduled quick scans + +Set to: `true` + +### DisableEmailScanning + +Indicates whether Windows Defender parses the mailbox and mail files, according to their specific format, in order to analyze mail bodies and attachments + +Set to: `false` + +### DisableIOAVProtection + +Indicates whether Windows Defender scans all downloaded files and attachments (e.g. Downloads) + +Set to: `true` + +### DisableIntrusionPreventionSystem + +Indicates whether to configure network protection against exploitation of known vulnerabilities + +Set to: `false` + +### DisablePrivacyMode + +Indicates whether to disable privacy mode. Privacy mode prevents users, other than administrators, from displaying threat history + +Set to: `false` + +### DisableRealtimeMonitoring + +Indicates whether to use real-time protection + +Set to: `false` + +### CheckForSignaturesBeforeRunningScan + +Set to: `1` + +### DisableRemovableDriveScanning + +Indicates whether to scan for malicious and unwanted software in removable drives, such as flash drives, during a full scan + +Set to: `true` + +### DisableRestorePoint + +Indicates whether to disable scanning of restore points + +Set to: `true` + +### DisableScanningMappedNetworkDrivesForFullScan + +Indicates whether to scan mapped network drives + +Set to: `true` + +### DisableScanningNetworkFiles + +Indicates whether to scan for network files + +Set to: `false` + +### DisableScriptScanning + +Specifies whether to disable the scanning of scripts during malware scans + +Set to: `false` + +### HighThreatDefaultAction + +Specifies which automatic remediation action to take for a high level threat + +Set to: `Quarantine` + +### LowThreatDefaultAction + +Specifies which automatic remediation action to take for a low level threat + +Set to: `Block` + +### ModerateThreatDefaultAction + +Specifies which automatic remediation action to take for a moderate level threat + +Set to: `Quarantine` + +### PUAProtection + +Disable PUA Protection + +Set to: `Enabled` + +### QuarantinePurgeItemsAfterDelay + +Specifies the number of days to keep items in the Quarantine folder + +Set to: `30` + +### RandomizeScheduleTaskTimes + +Indicates whether to select a random time for the scheduled start and scheduled update for definitions + +Set to: `true` + +### RealTimeScanDirection + +Specifies scanning configuration for incoming and outgoing files on NTFS volumes + +Set to: `0` + +### RemediationScheduleDay + +Specifies the day of the week on which to perform a scheduled full scan in order to complete remediation + +Set to: `Everyday` + +### RemediationScheduleTime + +Specifies the time of day, as the number of minutes after midnight, to perform a scheduled scan + +Set to: `120` + +### ReportingAdditionalActionTimeOut + +Specifies the number of minutes before a detection in the additional action state changes to the cleared state + +Set to: `10080` + +### ReportingCriticalFailureTimeOut + +Specifies the number of minutes before a detection in the critically failed state changes to either the additional action state or the cleared state + +Set to: `10080` + +### ReportingNonCriticalTimeOut + +Specifies the number of minutes before a detection in the non-critically failed state changes to the cleared state + +Set to: `11440` + +### ScanAvgCPULoadFactor + +Specifies the maximum percentage CPU usage for a scan + +Set to: `50` + +### ScanOnlyIfIdleEnabled + +Indicates whether to start scheduled scans only when the computer is not in use + +Set to: `true` + +### ScanParameters + +Specifies the scan type to use during a scheduled scan + +Set to: `1` + +### ScanPurgeItemsAfterDelay + +Specifies the number of days to keep items in the scan history folder + +Set to: `15` + +### ScanScheduleDay + +Specifies the day of the week on which to perform a scheduled scan + +Set to: `Everyday` + +### ScanScheduleQuickScanTime + +Specifies the time of day, as the number of minutes after midnight, to perform a scheduled quick scan + +Set to: `0` + +### ScanScheduleTime + +Specifies the time of day, as the number of minutes after midnight, to perform a scheduled scan + +Set to: `120` + +### SevereThreatDefaultAction + +Specifies which automatic remediation action to take for a severe level threat + +Set to: `Quarantine` + +### SignatureAuGracePeriod + +Specifies a grace period, in minutes, for the definition + +Set to: `0` + +### SignatureDisableUpdateOnStartupWithoutEngine + +Indicates whether to initiate definition updates even if no antimalware engine is present + +Set to: `false` + +### SignatureFirstAuGracePeriod + +Specifies a grace period, in minutes, for the definition. If a definition successfully updates within this period, Windows Defender abandons any service initiated updates + +Set to: `120` + +### SignatureScheduleDay + +Specifies the day of the week on which to check for definition updates + +Set to: `Everyday` + +### SignatureScheduleTime + +Specifies the time of day, as the number of minutes after midnight, to check for definition updates + +Set to: `165` + +### SignatureUpdateCatchupInterval + +Specifies the number of days after which Windows Defender requires a catch-up definition update + +Set to: `1` + +### SignatureUpdateInterval + +Specifies the interval, in hours, at which to check for definition updates + +Set to: `12` + +### SubmitSamplesConsent + +Specifies how Windows Defender checks for user consent for certain samples + +Set to: `AlwaysPrompt` + +### MAPSReporting + +Membership in Microsoft Active Protection Service Enable + +Set to: `Advanced` + +### ThrottleLimit + +Specifies the maximum number of concurrent operations that can be established to run the cmdlet + +Set to: `0` + +### UILockdown + +Indicates whether to disable UI lock down mode + +Set to: `false` + +### UnknownThreatDefaultAction + +Specifies which automatic remediation action to take for an unknown level threat + +Set to: `Block` + +### SignatureFallbackOrder + +Specifies the order in which to contact different definition update sources. Specify the types of update sources in the order in which you want Windows Defender to contact them, enclosed in braces and separated by the pipeline symbol + +Set to: `MicrosoftUpdateServer | MMPC` + +### ControlledFolderAccessAllowedApplications + +We exclude the following Files by default: `$env:windir\System32\taskhostw.exe` + +Any exclusions previously configured stay intact! + +### ExclusionPath + +The following Files/Folders are excluded from the scan: + +`windir\SoftwareDistribution\DataStore\Datastore.edb` +`windir\SoftwareDistribution\DataStore\Logs\Edb*.jrs` +`windir\SoftwareDistribution\DataStore\Logs\Edb.chk` +`windir\SoftwareDistribution\DataStore\Logs\Tmp.edb` +`windir\Security\Database\*.edb` +`windir\Security\Database\*.sdb` +`windir\Security\Database\*.log` +`windir\Security\Database\*.chk` +`windir\Security\Database\*.jrs` +`windir\Security\Database\*.xml` +`windir\Security\Database\*.csv` +`windir\Security\Database\*.cmtx` +`ProgramData\ntuser.pol` +`windir\System32\GroupPolicy\Machine\Registry.pol` +`windir\System32\GroupPolicy\Machine\Registry.tmp` +`windir\System32\GroupPolicy\User\Registry.pol` +`windir\System32\GroupPolicy\User\Registry.tmp` + +Any exclusions previously configured stay intact! + +More Info: [https://support.microsoft.com/en-us/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni](https://support.microsoft.com/en-us/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni) + +### ExclusionProcess + +The following processes are excluded from the scan: + +`$env:windir\System32\svchost.exe` +`$env:windir\System32\wuauclt.exe` + +Any exclusions previously configured stay intact! + +More Info: [https://support.microsoft.com/en-us/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni](https://support.microsoft.com/en-us/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni) + +### Process Mitigation and Exploit Protection + +Microsoft provides a XML file (`ProcessMitigation.xml`) that provides a configuration best practice to mitigate the attack surface and provide Exploit Protection. + +You can provide your own File, otherwise (if missing) we will download the latest version from Microsoft. + +More Info: [https://demo.wd.microsoft.com/Page/EP](https://demo.wd.microsoft.com/Page/EP) + +### WindowsDefenderSandbox + +We tuen on Windows Defender Sandbox + +### AttackSurfaceReduction + +Attack Surface Reduction (ASR) is comprised of a number of rules, each of which target specific behaviors that are typically used by malware and malicious apps to infect machines, such as: + +- Executable files and scripts used in Office apps or web mail that attempt to download or run files +- Scripts that are obfuscated or otherwise suspicious +- Behaviors that apps undertake that are not usually initiated during normal day-to-day work + +More Info: [https://demo.wd.microsoft.com/Page/ASR](https://demo.wd.microsoft.com/Page/ASR) + +### ReloadRegistry + +We then reload the registry to ensure that the new configuration is activated + +### EnableFirewall + +Enable the Windows Firewall for all Profiles - Set the default to block everything + +We enable the Windows Firewall for the following Network-Profiles: + +- Domain +- Public +- Private + +We block all inbound connections by default and we log all block-events! + +### UpdateSignature + +As a final touch: We update the Windows Defender signatures. + +## Why this? + +I use this during the bootstrap process of Windows systems. +Most of the settings here is also enforced by some of our Group Policies and we also have a lot of it configured via MDM CSPs (InTune). + +This script is only a quick hack to harden (and secure) any new system, even if it is not managed afterwords. + +## Content + +There are two files: + +### Bootstrap-MicrosoftDefenderConfiguration.ps1 + +The PowerShell Script itself + +### Bootstrap-MicrosoftDefenderConfiguration.csv + +A CSV File that contains the configuration of the attack surface reduction rules. + +## Configuration + +Please review the `Bootstrap-MicrosoftDefenderConfiguration.csv` where you configure the attack surface reduction rules. Please also review the `Bootstrap-MicrosoftDefenderConfiguration.ps1` file. There is no configuration file, at least not yet! + +## Further Information + +[https://docs.microsoft.com/en-us/powershell/module/defender/index?view=win10-ps](https://docs.microsoft.com/en-us/powershell/module/defender/index?view=win10-ps) + +[https://github.com/jhochwald/PowerShell-collection/blob/master/Misc/Optimize-MicrosoftDefenderExclusions.ps1](https://github.com/jhochwald/PowerShell-collection/blob/master/Misc/Optimize-MicrosoftDefenderExclusions.ps1) + +[https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/enable-exploit-protection](https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/enable-exploit-protection +) + +[https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=win10-ps](https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=win10-ps) + +[https://docs.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/customize-attack-surface-reduction](https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=win10-ps) + +[https://support.microsoft.com/en-us/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni](https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=win10-ps) + +[https://docs.microsoft.com/en-us/windows/security/threat-protection/windows-defender-antivirus/enable-cloud-protection-windows-defender-antivirus](https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=win10-ps) + +[https://demo.wd.microsoft.com/?ocid=cx-wddocs-testground](https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference?view=win10-ps) + +## License + +BSD 3-Clause License + +Copyright (c) 2020, Joerg Hochwald +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Misc/Check-ServiceMonitor.ps1 b/Powershell/PowerShell-collection/Misc/Check-ServiceMonitor.ps1 new file mode 100644 index 0000000..c39e968 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Check-ServiceMonitor.ps1 @@ -0,0 +1,158 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Quick an dirty Windows Service Monitor + + .DESCRIPTION + I came across the the problem, that one of the services I depend one was not started after the system reboots. + That happens after a .NET update. So I decided to create this real simple monitor to make sure, that this service is running. + If not, the script tries to restart it. + + .PARAMETER MonService + The Service we would like to check. Default is RoyalServer + + .EXAMPLE + PS C:\> .\Check-ServiceMonitor.ps1 + + .EXAMPLE + PS C:\> .\Check-ServiceMonitor.ps1 -MonService 'myservice' + + .NOTES + The script itself have some basic error handling, + nothing to complex or fancy. +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + Position = 1)] + [Alias('ServiceToMonitor')] + [string] + $MonService = 'RoyalServer' +) + +begin +{ + [string]$SC = 'SilentlyContinue' + [string]$STP = 'Stop' +} + +process +{ + # Get the Status + try + { + Write-Verbose -Message ('Get the Status of {0}' -f $MonService) + + $paramGetService = @{ + Name = $MonService + ErrorAction = $STP + WarningAction = $SC + } + + [string]$MonServiceStatus = ((Get-Service @paramGetService).Status) + + Write-Verbose -Message ('We have the Status of {0}' -f $MonService) + } + catch + { + Write-Error -Message ('Looks like the Service {0} is not installed!' -f $MonService) -ErrorAction $STP + + # Point of no return (Should never be reached) + break + } + + + # Do the check + if ($MonServiceStatus -ne 'Running') + { + Write-Warning -Message ('Sorry, but {0} is not running ' -f $MonService) + + try + { + Write-Verbose -Message ('Try to restart {0}' -f $MonService) + + $MonParam = @{ + Name = $MonService + Confirm = $false + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Restart-Service @MonParam) + } + catch + { + # Whooooops! Try it again... Let us try to stop the services + + Write-Verbose -Message ('Try to stop {0}' -f $MonService) + $null = (Stop-Service @MonParam) + + # Wait a second + $null = (Start-Sleep -Seconds 1) + + # Try to stop it again... + $null = (Stop-Service @MonParam) + + # Wait a second + $null = (Start-Sleep -Seconds 1) + + # Try to kill it, again! + $null = (Stop-Service @MonParam) + + # Wait two seconds to cool down + Write-Verbose -Message ('Try to start {0}' -f $MonService) + + $null = (Start-Sleep -Seconds 2) + + try + { + # Now let us try to start the service + Write-Verbose -Message ('Try to start {0} again!' -f $MonService) + + $null = (Start-Service @MonParam) + } + catch + { + # Dude, this is bad! And I mean real bad!!! + Write-Error -Message ('We where not able to start {0} - Might be a good idea to reboot this system' -f $MonService) + } + } + } + else + { + # Looks good so far + Write-Verbose -Message ('Looks like {0} is doing great...' -f $MonService) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs.ps1 b/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs.ps1 new file mode 100644 index 0000000..a9d4299 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs.ps1 @@ -0,0 +1,84 @@ +function Clear-EnAllEventLogs +{ + <# + .SYNOPSIS + AllEventLlogs + + .DESCRIPTION + AllEventLlogs + + .PARAMETER ComputerName + Computer Name + + .EXAMPLE + PS C:\> Clear-EnAllEventLogs + + .NOTES + N.N. + #> + [CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [string[]] + $ComputerName = "$env:COMPUTERNAME" + ) + + process + { + + foreach ($SingleComputerName in $ComputerName) + { + if ($pscmdlet.ShouldProcess($SingleComputerName, 'Cleanup All EventLogs')) + { + $paramGetEventLog = @{ + ComputerName = $SingleComputerName + List = $true + } + $null = (Get-EventLog @paramGetEventLog | ForEach-Object -Process { + if ($_.Entries) + { + $paramClearEventLog = @{ + LogName = $_.Log + Confirm = $false + ErrorAction = 'SilentlyContinue' + } + $null = (Clear-EventLog @paramClearEventLog) + } + }) + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs_TESTS.ps1 b/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs_TESTS.ps1 new file mode 100644 index 0000000..482d534 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs_TESTS.ps1 @@ -0,0 +1,373 @@ +#requires -Version 4.0 + +<# + .SYNOPSIS + Compare a old and a refactored function to get any Performace differences + + .DESCRIPTION + This script compares a simple function (That deletes all Windows Eventlog Entries) with an refacored one. + The request came up during a workshop: I was asked why I use pipes so much and if there is another way, without pipes. + + The refactored version was created during the workshop as a prototype. + And to make it easier to compare them, I created this test script. + + .EXAMPLE + PS C:\> .\Clear-EnAllEventLogs_TESTS.ps1 + + .NOTES + Releasenotes: + 1.0.0 2019-07-24 Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + NONE + + .LINK + https://www.enatec.io +#> +[CmdletBinding(ConfirmImpact = 'None')] +[OutputType([psobject])] +param () + +#region VersionOfJosh +function Clear-EnAllEventLogs +{ + <# + .SYNOPSIS + Delete all Windows event log entries + + .DESCRIPTION + Delete all Windows event log entries, without any further interaction. + I use this only after I do some tests on a virtual machine. + + Please Note: + It Might be dangerous! It might delete more than you like. + + Warning: + All security related will also be removed completely. + If there were any issues, you might never find any information about it! + + .PARAMETER ComputerName + Computer Name as String. Multi Value is possible + + .EXAMPLE + PS C:\> Clear-EnAllEventLogs + + Delete all Windows EventLog Entries on the local Computer. + + .EXAMPLE + PS C:\> Clear-EnAllEventLogs -ComputerName FRADC01 + + Delete all Windows EventLog Entries on the Computer with the name FRADC01. + + .EXAMPLE + PS C:\> Clear-EnAllEventLogs -ComputerName 'FRADC01', 'FRADC02' + + Delete all Windows EventLog Entries on the Computers with the names FRADC01 and FRADC02. + + .NOTES + Releasenotes: + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + TNONE + + .LINK + https://www.enatec.io + + .LINK + about_foreach + + .LINK + Foreach-Object + + .LINK + Get-EventLog + + .LINK + Clear-EventLog + #> + [CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [string[]] + $ComputerName = "$env:COMPUTERNAME" + ) + + process + { + + foreach ($SingleComputerName in $ComputerName) + { + if ($pscmdlet.ShouldProcess($SingleComputerName, 'Cleanup All EventLogs')) + { + $paramGetEventLog = @{ + ComputerName = $SingleComputerName + List = $true + } + $null = (Get-EventLog @paramGetEventLog | ForEach-Object -Process { + if ($_.Entries) + { + $paramClearEventLog = @{ + LogName = $_.Log + Confirm = $false + ErrorAction = 'SilentlyContinue' + } + $null = (Clear-EventLog @paramClearEventLog) + } + }) + } + } + } +} +#endregion VersionOfJosh + +#region RefactoredVersion +function Clear-EnAllEventLogsv2 +{ + <# + .SYNOPSIS + Delete all Windows event log entries + + .DESCRIPTION + Delete all Windows event log entries, without any further interaction. + I use this only after I do some tests on a virtual machine. + + Please Note: + It Might be dangerous! It might delete more than you like. + + Warning: + All security related will also be removed completely. + If there were any issues, you might never find any information about it! + + .PARAMETER ComputerName + Computer Name as String. Multi Value is possible + + .EXAMPLE + PS C:\> Clear-EnAllEventLogsv2 + + Delete all Windows EventLog Entries on the local Computer. + + .EXAMPLE + PS C:\> Clear-EnAllEventLogsv2 -ComputerName FRADC01 + + Delete all Windows EventLog Entries on the Computer with the name FRADC01. + + .EXAMPLE + PS C:\> Clear-EnAllEventLogsv2 -ComputerName 'FRADC01', 'FRADC02' + + Delete all Windows EventLog Entries on the Computers with the names FRADC01 and FRADC02. + + .NOTES + Releasenotes: + 2.0.0 2019-07-23: Refactored version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + NONE + + .LINK + https://www.enatec.io + + .LINK + about_foreach + + .LINK + Foreach-Object + + .LINK + Get-EventLog + + .LINK + Clear-EventLog + #> + [CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [string[]] + $ComputerName = "$env:COMPUTERNAME" + ) + + process + { + + foreach ($SingleComputerName in $ComputerName) + { + if ($pscmdlet.ShouldProcess($SingleComputerName, 'Cleanup All EventLogs')) + { + $paramGetEventLog = @{ + ComputerName = $SingleComputerName + List = $true + } + $null = ((Get-EventLog @paramGetEventLog).Where( { + if ($_.Entries) + { + $_ + } + }).ForEach( { + $paramClearEventLog = @{ + LogName = $_.Log + Confirm = $false + ErrorAction = 'SilentlyContinue' + } + $null = (Clear-EventLog @paramClearEventLog) + })) + } + } + } +} +#endregion RefactoredVersion + +#region CreateTestData +function Invoke-CreateTestData +{ + <# + .SYNOPSIS + Create 10.000 dummy entries + + .DESCRIPTION + Create 10.000 dummy entries + + .EXAMPLE + PS C:\> Invoke-CreateTestData + + .NOTES + Internal Helper Function to create some useless Test Data + + Releasenotes: + 1.0.1 2019-07-23: Splat the parameters for better radability + 1.0.0 2019-07-23: Initial Version + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + NONE + + .LINK + https://www.enatec.io + + .LINK + Write-EventLog + + .LINK + about_foreach + + .LINK + Foreach-Object + #> + + [CmdletBinding(ConfirmImpact = 'None')] + param () + + begin + { + # Splat the parameters + $paramWriteEventLog = @{ + LogName = 'Application' + EventId = 2001 + EntryType = 'Information' + Source = 'HAL9000' + Message = 'I think you know what the problem is just as well as I do.' + ErrorAction = 'SilentlyContinue' + } + } + + process + { + # Change the number to fit your needs + 1 .. 1000 | ForEach-Object -Process { + $null = (Write-EventLog @paramWriteEventLog) + } + } +} +#endregion CreateTestData + +# Initial Cleanup +$null = (Clear-EnAllEventLogs -ErrorAction SilentlyContinue) + +# Create a few new objects +$OldWayAverage = @() +$OldWaySum = @() +$NewWayAverage = @() +$NewWaySum = @() + +# Create the new Eventlog +$null = (New-EventLog -LogName Application -Source 'HAL9000' -ErrorAction SilentlyContinue) + +#region OldWay +$null = (1..10 | ForEach-Object { + # Create some Test Data + $null = (Invoke-CreateTestData -ErrorAction SilentlyContinue) + + #region OldWaySingle + $OldWaySingle = (Measure-Command -Expression { + $null = (Clear-EnAllEventLogs -ErrorAction SilentlyContinue) + }) + #endregion OldWaySingle + $OldWaySum += $OldWaySingle + }) +$OldWayAverage = (($OldWaySum | Measure-Object -Property TotalMilliseconds -Average).Average) +#endregion OldWay + +#region NewWay +$null = (1..10 | ForEach-Object { + # Create some Test Data + $null = (Invoke-CreateTestData -ErrorAction SilentlyContinue) + + #region NewWaySingle + $NewWaySingle = (Measure-Command -Expression { + $null = (Clear-EnAllEventLogsv2 -ErrorAction SilentlyContinue) + }) + #endregion NewWaySingle + $NewWaySum += $NewWaySingle + }) +$NewWayAverage = (($NewWaySum | Measure-Object -Property TotalMilliseconds -Average).Average) +#endregion NewWay + +#Region DumpData +Write-Verbose -Message 'Time measured in milliseconds' -Verbose + +[pscustomobject]@{ + OldWay = $OldWayAverage + NewWay = $NewWayAverage +} +#endregion DumpData + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs_v2.ps1 b/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs_v2.ps1 new file mode 100644 index 0000000..cbcf8c8 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Clear-EnAllEventLogs_v2.ps1 @@ -0,0 +1,85 @@ +function Clear-EnAllEventLogsv2 +{ + <# + .SYNOPSIS + AllEventLlogs + + .DESCRIPTION + AllEventLlogs + + .PARAMETER ComputerName + Computer Name + + .EXAMPLE + PS C:\> Clear-EnAllEventLogsv2 + + .NOTES + N.N. + #> + [CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [string[]] + $ComputerName = "$env:COMPUTERNAME" + ) + + process + { + foreach ($SingleComputerName in $ComputerName) + { + if ($pscmdlet.ShouldProcess($SingleComputerName, 'Cleanup All EventLogs')) + { + $paramGetEventLog = @{ + ComputerName = $SingleComputerName + List = $true + } + $null = ((Get-EventLog @paramGetEventLog).Where( { + if ($_.Entries) + { + $_ + } + }).ForEach( { + $paramClearEventLog = @{ + LogName = $_.Log + Confirm = $false + ErrorAction = 'SilentlyContinue' + } + $null = (Clear-EventLog @paramClearEventLog) + })) + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/DisableDotNetTelemetry.ps1 b/Powershell/PowerShell-collection/Misc/DisableDotNetTelemetry.ps1 new file mode 100644 index 0000000..44fd963 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/DisableDotNetTelemetry.ps1 @@ -0,0 +1,6 @@ +# Disable the .NET Telemetry on production servers and critical workstations +[Environment]::SetEnvironmentVariable('DOTNET_CLI_TELEMETRY_OPTOUT', '1', 'Machine') +[Environment]::SetEnvironmentVariable('MLDOTNET_CLI_TELEMETRY_OPTOUT', '1', 'Machine') + +# Tweak the 1st run experience +[Environment]::SetEnvironmentVariable('DOTNET_SKIP_FIRST_TIME_EXPERIENCE', '1', 'Machine') diff --git a/Powershell/PowerShell-collection/Misc/Enable-DNSOverHTTPS.ps1 b/Powershell/PowerShell-collection/Misc/Enable-DNSOverHTTPS.ps1 new file mode 100644 index 0000000..6958b31 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Enable-DNSOverHTTPS.ps1 @@ -0,0 +1,272 @@ +#requires -Version 3.0 -Modules CimCmdlets, DnsClient, NetAdapter, NetTCPIP -RunAsAdministrator + +<# + .SYNOPSIS + Enable DNS-over-HTTPS (DoH) if device is not domain-joined + + .DESCRIPTION + Enable DNS-over-HTTPS (DoH) if device is not domain-joined + + It enables the Cloudflare DNS Servers, even if DoH is not working yet. + + IPv6 Support is optional. + + .PARAMETER IPv6 + Enable IPv6 Support, IPv6 Servers will be added to the serverlist + + .EXAMPLE + PS C:\> .\Enable-DNSOverHTTPS.ps1 + + Enable DNS-over-HTTPS (DoH) if device is not domain-joined for IPv4 only + + .EXAMPLE + PS C:\> .\Enable-DNSOverHTTPS.ps1 -IPv6 + + Enable DNS-over-HTTPS (DoH) if device is not domain-joined for IPv4 and IPv6 + + .NOTES + Only the Insider Build of Windows 10 supports DoH! + But we configure it anyway! + + The Cloudflare servers are used for regular DNS resolution and as soon as DoH is supported, + we can configure and use it anyway. + + A future version of this script might support additional parameters, like DohFlags + + You can also change the servers below to any service you like, e.g. Google DNS or Quad9 from IBM. + + The Bool as return was requested by a customer, and the exit code (0 or 1) is implemented for our bootstrap setup + + .LINK + https://1.1.1.1/dns/ + + .LINK + https://techcommunity.microsoft.com/t5/networking-blog/windows-insiders-can-now-test-dns-over-https/ba-p/1381282 +#> +[CmdletBinding(ConfirmImpact = 'None')] +[OutputType([bool])] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('IP6', '6')] + [switch] + $IPv6 +) + +begin +{ + #region Defaults + $SCT = 'SilentlyContinue' + $STP = 'Stop' + $CNT = 'Continue' + + # Save the infos from the switches + if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + { + $IsVerbose = $true + } + else + { + $IsVerbose = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) + { + $IsDebug = $true + } + else + { + $IsDebug = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['WhatIf']).IsPresent) + { + $IsWhatIf = $true + } + else + { + $IsWhatIf = $false + } + #endregion Defaults + + #region ServerAddresses + # Create an Empty Object + $ServerAddresses = @() + + # IPv4 DNS Servers to use + $ServerAddressesIPv4 = @( + '1.1.1.1' + '1.0.0.1' + ) + + # Add the IPv4 Servers to the Object + $ServerAddresses += $ServerAddressesIPv4 + + if ((($PSCmdlet.MyInvocation.BoundParameters['IPv6']).IsPresent) -eq $true) + { + Write-Verbose -Message 'IPv6 Servers will be added to the serverlist' + # IPv6 DNS Servers to use + $ServerAddressesIPv6 = @( + '2606:4700:4700::1111' + '2606:4700:4700::1001' + ) + + # Add the IPv6 Servers to the Object + $ServerAddresses += $ServerAddressesIPv6 + } + #endregion ServerAddresses +} + +process +{ + #region DoH + # Enable DNS-over-HTTPS for IPv4 if device is not domain-joined + $paramGetCimInstance = @{ + ClassName = 'CIM_ComputerSystem' + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $STP + } + if (((Get-CimInstance @paramGetCimInstance).PartOfDomain) -eq $false) + { + try + { + # Temporarily key + $paramNewItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' + Name = 'EnableAutoDoh' + Value = 2 + PropertyType = 'DWord' + Force = $true + WhatIf = $IsWhatIf + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $CNT + } + $null = (New-ItemProperty @paramNewItemProperty) + + $paramGetNetAdapter = @{ + Verbose = $IsVerbose + Debug = $IsDebug + Physical = $true + ErrorAction = $SCT + } + $MACAddress = ((Get-NetAdapter @paramGetNetAdapter).MacAddress) + + $paramGetNetIPConfiguration = @{ + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $SCT + } + $IpConfig = (Get-NetIPConfiguration @paramGetNetIPConfiguration | Where-Object -FilterScript { + $MACAddress -eq $_.NetAdapter.MacAddress + }) + + $paramSetDnsClientServerAddress = @{ + ServerAddresses = $ServerAddresses + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $CNT + } + $null = ($IpConfig | Set-DnsClientServerAddress @paramSetDnsClientServerAddress) + + $paramClearDnsClientCache = @{ + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $SCT + } + $null = (Clear-DnsClientCache @paramClearDnsClientCache) + + $paramRegisterDnsClient = @{ + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $SCT + } + $null = (Register-DnsClient @paramRegisterDnsClient) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $CNT + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + } + else + { + $paramWriteError = @{ + Message = 'Sorry, this computer seems to be part of a Active Directory domain!' + Exception = 'Active Directory Domain Members are not supported' + Category = 'NotEnabled' + TargetObject = $env:COMPUTERNAME + ErrorAction = $CNT + } + Write-Error @paramWriteError + + # Return the Bool + Write-Output -InputObject $false + + # Unclean exit + exit 1 + } + #endregion DoH +} + +end +{ + # Return the Bool + Write-Output -InputObject $true + + # Clean exit + exit 0 +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/ForceTimeResync.ps1 b/Powershell/PowerShell-collection/Misc/ForceTimeResync.ps1 new file mode 100644 index 0000000..a7996c4 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/ForceTimeResync.ps1 @@ -0,0 +1,56 @@ +#requires -RunAsAdministrator + +<# + .SYNOPSIS + Force Time re-sync with PowerShell + + .DESCRIPTION + Force Time re-sync as a PowerShell script + + .EXAMPLE + PS C:\> .\ForceTimeResync.ps1 + + Force Time Resync as a PowerShell script (Wrapper for w32tm.exe). Most be executed in an elevated shell) + + .NOTES + One of my VM's did a view time travels in the past. This little script runs every hour (Task). + I still try to find the cause for the time travels (It jumps 2 hours forward, from time to time) and a better PowerShell way to do it. + For now, this quick and dirty solution works just fine. +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +process +{ + $null = (& "$env:windir\system32\w32tm.exe" /resync /force) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Get-AllCookiesFromWebRequestSession.ps1 b/Powershell/PowerShell-collection/Misc/Get-AllCookiesFromWebRequestSession.ps1 new file mode 100644 index 0000000..117b014 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-AllCookiesFromWebRequestSession.ps1 @@ -0,0 +1,114 @@ +function Get-AllCookiesFromWebRequestSession +{ + <# + .SYNOPSIS + Get all cookies stored in the WebRequestSession variable from any Invoke-RestMethod and/or Invoke-WebRequest request + + .DESCRIPTION + Get all cookies stored in the WebRequestSession variable from any Invoke-RestMethod and/or Invoke-WebRequest request + The WebRequestSession stores useful info and it has something that some my know as CookieJar or http.cookiejar. + + .PARAMETER WebRequestSession + Specifies a variable where Invoke-RestMethod and/or Invoke-WebRequest saves values. + Must be a valid [Microsoft.PowerShell.Commands.WebRequestSession] object! + + .EXAMPLE + PS C:\> $null = Invoke-WebRequest -UseBasicParsing -Uri 'http://jhochwald.com' -Method Get -SessionVariable WebSession -ErrorAction SilentlyContinue + PS C:\> $WebSession | Get-AllCookiesFromWebRequestSession + + Get all cookies stored in the $WebSession variable from the request above. + This page doesn't use or set any cookies, but the (awesome) CloudFlare service does. + + .EXAMPLE + $null = Invoke-RestMethod -UseBasicParsing -Uri 'https://jsonplaceholder.typicode.com/todos/1' -Method Get -SessionVariable RestSession -ErrorAction SilentlyContinue + $RestSession | Get-AllCookiesFromWebRequestSession + + Get all cookies stored in the $RestSession variable from the request above. + Please do not abuse the free API service above! + + .NOTES + I used something I had stolen from Chrissy LeMaire's TechNet Gallery entry a (very) long time ago. + But I needed something more generic, independent from the URL! This can become handy, to find any cookie from a 3rd party site or another host. + + .LINK + https://docs.python.org/3/library/http.cookiejar.html + + .LINK + https://en.wikipedia.org/wiki/HTTP_cookie + + .LINK + https://gallery.technet.microsoft.com/scriptcenter/Getting-Cookies-using-3c373c7e + + .LINK + Invoke-RestMethod + + .LINK + Invoke-WebRequest + #> + + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Specifies a variable where Invoke-RestMethod and/or Invoke-WebRequest saves values.')] + [ValidateNotNull()] + [Alias('Session', 'InputObject')] + [Microsoft.PowerShell.Commands.WebRequestSession] + $WebRequestSession + ) + + begin + { + # Do the housekeeping + $CookieInfoObject = $null + } + + process + { + try + { + # I know, this look very crappy, but it just work fine! + [pscustomobject]$CookieInfoObject = ((($WebRequestSession).Cookies).GetType().InvokeMember('m_domainTable', [Reflection.BindingFlags]::NonPublic -bor [Reflection.BindingFlags]::GetField -bor [Reflection.BindingFlags]::Instance, $null, (($WebRequestSession).Cookies), @())) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + } + + end + { + # Dump the Cookies to the Console + ((($CookieInfoObject).Values).Values) + } +} diff --git a/Powershell/PowerShell-collection/Misc/Get-DirectorySize.ps1 b/Powershell/PowerShell-collection/Misc/Get-DirectorySize.ps1 new file mode 100644 index 0000000..473f1e4 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-DirectorySize.ps1 @@ -0,0 +1,134 @@ +function Get-DirectorySize +{ + <# + .SYNOPSIS + Get the size of a given folder in a human readable format + + .DESCRIPTION + Get the size of a given folder in a human readable format + + .PARAMETER Path + Folder to check + + .PARAMETER Type + Type of the Return, + Valid values are: GB, MB, KB, B + The default is MB (Megabyte) + + .EXAMPLE + PS C:\> Get-DirectorySize -Path 'C:\scripts' + + .EXAMPLE + PS C:\> Get-DirectorySize -Path 'C:\scripts' -Type GB + + .NOTES + PowerShell function to emulate the wel known Linux DU command + + Releasenotes: + 1.0.0 2019-05-09: Initial Release + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([string])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('Directory', 'Folder')] + [string] + $Path = '.', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [ValidateSet('GB', 'MB', 'KB', 'B', IgnoreCase = $true)] + [Alias('InType')] + [string] + $Type = 'MB' + ) + + process + { + try + { + $AllFolderItems = (Get-ChildItem -Path $Path -Recurse -ErrorAction Stop | Measure-Object -Property length -Sum) + + switch ($Type) + { + 'GB' + { + $FolderSize = '{0:N2}' -f ($AllFolderItems.sum / 1GB) + ' GB' + } + 'MB' + { + $FolderSize = '{0:N2}' -f ($AllFolderItems.sum / 1MB) + ' MB' + } + 'KB' + { + $FolderSize = '{0:N2}' -f ($AllFolderItems.sum / 1KB) + ' KB' + } + 'B' + { + $FolderSize = '{0:N2}' -f ($AllFolderItems.sum) + ' B' + } + Default + { + $FolderSize = '{0:N2}' -f ($AllFolderItems.sum) + ' MB' + } + } + + return $FolderSize + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message $e.Exception.Message -ErrorAction Continue -Exception $e.Exception -TargetObject $e.CategoryInfo.TargetName + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Get-FritzBoxEvents.ps1 b/Powershell/PowerShell-collection/Misc/Get-FritzBoxEvents.ps1 new file mode 100644 index 0000000..de55234 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-FritzBoxEvents.ps1 @@ -0,0 +1,463 @@ +function Get-FritzBoxEvents +{ + <# + .SYNOPSIS + Get the Events from a FritzBox router + + .DESCRIPTION + Get the Events from a FritzBox router + + .PARAMETER FritzBoxUser + Username to use for the FritzBox login + + .PARAMETER FritzBoxPassword + FritzBox Password in plain text (might be changed to a secure string soon) + + .PARAMETER FritzBoxHost + The URI that contains the FQDN or IP of your FritzBox, + e.g. http://fritz.box or http://192.168.178.1 + + .PARAMETER Hours + Hours to get, e.g. 24 + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' -Hours 24 | Where-Object {(($_.ipv4 -ne $null) -or ($_.ipv6 -ne $null))} + + Get only entries with IPv4 or IPv6 values, of the last 24 hours + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' -Hours 48 | Where-Object {($_.ipv6 -ne $null)} + + Get only entries with IPv6 values, of the last 48 hours + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like 'Die Systemzeit wurde erfolgreich aktualisiert von Zeitserver*')} + + Get all events where the time was set via a time server, no time limit + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like 'Die Systemzeit wurde erfolgreich aktualisiert von Zeitserver*')} | Select-Object -ExpandProperty IPv4 + + Get all events where the time was set via a time server, only return the IPv4 addresses, no time limit + + .EXAMPLE + PS C:\> ((Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like 'Die Systemzeit wurde erfolgreich aktualisiert von Zeitserver*')})[0] | Select-Object -ExpandProperty IPv4) + + Get all events where the time was set via a time server, only return the IPv4 address of the latest (youngest) event + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like '*main-repeater*')} + + Only return events from a repeater with the name main-repeater, no time limit + + .EXAMPLE + PS C:\> (Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like '*main-repeater*')})[0] + + Only return the latest (youngest) events from a repeater with the name main-repeater, no time limit + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like '*Zeitserver * antwortet nicht.')} + + Only return events where the Timeserver does NOT answer, no time limit + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like '*verschlüsselten DNS-Servern*')} + + All events related to encrypted DNS, no time limit + + .EXAMPLE + PS C:\> Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' -Hours 24 | Where-Object {($_.Message -like '*Authentifizierungsfehler*')} + + Only events with authentication errors, of the last 24 hours + + .EXAMPLE + PS C:\> ((Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like '*(verfügbare Bitrate)*')})[0] | Select-Object -ExpandProperty Message) + + The latest (youngest) event that has the bitrate info (capacity) + + .EXAMPLE + PS C:\> ((Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like 'Internetverbindung wurde erfolgreich hergestellt.*')})[0] | Select-Object -ExpandProperty IPv4) + + Get the public IPv4 address + + .EXAMPLE + PS C:\> ((Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {($_.Message -like 'Internetverbindung IPv6 wurde erfolgreich hergestellt.*')})[0] | Select-Object -ExpandProperty IPv6) + + Get the public IPv6 address + + .EXAMPLE + PS C:\> ((Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {(($_.Message -like '*IPv6-Präfix wurde erfolgreich bezogen.*') -and ($_.ipv6 -ne $null))})[0] | Select-Object -ExpandProperty IPv6) + + Get the latest public IPv6 prefix (CIDR) + + .EXAMPLE + PS C:\> ((Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {(($_.Message -like 'Freigabe als Exposed Host auf * (*) hinzugefügt.') -and ($_.ipv4 -ne $null))})[0] | Select-Object -ExpandProperty IPv4) + + get the exposed host IPv4 + + .EXAMPLE + PS C:\> $IPv6TMP = (Get-FritzBoxEvents -FritzBoxUser 'myFritz' -FritzBoxPassword 'ThePassw0rd' -FritzBoxHost 'http://myfritz.box' | Where-Object {(($_.Message -like 'Freigabe als Exposed Host auf * (*) hinzugefügt.') -and ($_.ipv4 -eq $null))} | Select-Object -ExpandProperty Message) + PS C:\> $regex = [regex]'(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))' + PS C:\> $regex.Matches($IPv6TMP) | ForEach-Object{ $_.value } + + Get the exposed host IPv6 address and/or IPv6 CIDR (of exists) + + .LINK + https://github.com/jangeisbauer/FritzBox2Sentinel + + .LINK + https://gist.github.com/joasch/e48738417ec1efcc963a96bbb3f34cba + + .LINK + https://www.ip-phone-forum.de/threads/ereignisprotokoll-der-fritz-box-auf-linux-server-sichern.280328/page-5 + + .NOTES + All tests in the examples are only valid if your FritzBox has a german UI! + For other languages, dump all events and search for the matches in your own language + + If you have issues with german umlauts, use the following before stating the command: + [console]::OutputEncoding = [System.Text.Encoding]::GetEncoding(1252) + + I had issues on macOS and Linux with german umlauts, never happened on Windows! + + Idea is stolen from https://github.com/jangeisbauer/FritzBox2Sentinel (No license was applied) + So, @jangeisbauer is considered as a contributor + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([array])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [Alias('FBUser', 'user')] + [string] + $FritzBoxUser = $null, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [Alias('Password', 'fbpassword')] + [string] + $FritzBoxPassword = $null, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [Alias('fbhost', 'host', 'fritzbox')] + [string] + $FritzBoxHost = 'http://fritz.box', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [int] + $Hours = $null + ) + + begin + { + # Garbage Collection + [GC]::Collect() + + #region Helper + function Get-MD5Hash + { + <# + .SYNOPSIS + Return a MD5 hash of a given String + + .DESCRIPTION + Return a MD5 hash of a given String + + .PARAMETER Text + String to convert + + .EXAMPLE + PS C:\> Get-MD5Hash -Text 'Value1' + + .LINK + https://github.com/jangeisbauer/FritzBox2Sentinel + + .NOTES + Cheap internal helper + + Stolen from https://github.com/jangeisbauer/FritzBox2Sentinel (No license was applied) + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([string])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'String to convert')] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [string] + $Text + ) + + begin + { + $md5 = (New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider) + } + + process + { + $md5.ComputeHash([Text.Encoding]::utf8.getbytes($Text)) | ForEach-Object -Process { + $HC = '' + } { + $HC += $_.tostring('x2') + } { + $HC + } + } + } + #endregion Helper + } + + process + { + try + { + # Convert the plain text password to a secure string + $FritzBoxSecurePassword = ($FritzBoxPassword | ConvertTo-SecureString -AsPlainText -Force -ErrorAction Stop) + + # FritzBox Pages to get + $FritzBoxLoginPage = '/login_sid.lua' + $FritzBoxEventPage = '/query.lua?mq_log=logger:status/log&sid=' + + # Secret handler + $SecureStringToBSTR = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($FritzBoxSecurePassword) + $PtrToStringAuto = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($SecureStringToBSTR) + + # Get the challenge from the FritzBox Login Page + $ChallengeRequest = (Invoke-WebRequest -Uri ($FritzBoxHost + $FritzBoxLoginPage) -UseBasicParsing -ErrorAction Stop) + + # Save the recived challenge + $Challenge = ([xml]$ChallengeRequest).sessioninfo.challenge + + # Create the input for the HEX code + $Code1 = ($Challenge + '-' + $PtrToStringAuto) + + # Create the HEX data string + $Code2 = ([char[]]$Code1 | ForEach-Object -Process { + $Code2 = '' + } { + $Code2 += $_ + [Char]0 + } { + $Code2 + }) + + # Create the body part for the next request (includes the MD5 hash of the HEX from above) + $SIDRequestBody = ('response=' + $Challenge + '-' + $(Get-MD5Hash -text ($Code2)) + '&username=' + $FritzBoxUser) + + # Do the real Login + $SIDRequest = (Invoke-WebRequest -Uri ($FritzBoxHost + $FritzBoxLoginPage) -Method Post -Body $SIDRequestBody -ErrorAction Stop) + + # Extract the SID from the Login request + $SID = ((([xml]($SIDRequest.Content)).ChildNodes).sid) + + # Get the Events + + $FritzBoxEvents = (Invoke-WebRequest -Uri ($FritzBoxHost + $FritzBoxEventPage + $SID) -UseBasicParsing -ErrorAction Stop) + + # Do we have a time limit? + if ($Hours -ne 0) + { + # Create a filter + $Filterhours = ((Get-Date).AddHours(-$Hours)) + } + else + { + # No filter needed + $Filterhours = $null + } + + # Create a new Array + $FritzEvents = @() + + # loop over the events we have (and extract the JSON return that contains all events) + foreach ($FritzBoxEvent in ($FritzBoxEvents.Content | ConvertFrom-Json -ErrorAction Stop).mq_log) + { + try + { + # Cleanup + $EventDate = $null + $IPv6 = $null + $IPv4 = $null + $EventEntry = $null + + # Transform the Data + $EventDate = [regex]::Matches($FritzBoxEvent, '\d\d\.\d\d\.\d\d \d\d:\d\d:\d\d')[0].Value + + # This REGEX should match IPv6 and IPv6 CIDR + $IPv6 = [regex]::Matches($FritzBoxEvent[0], '((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]d|1dd|[1-9]?d)(.(25[0-5]|2[0-4]d|1dd|[1-9]?d)){3}))|:)))(%.+)?s*(\/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8]))?$')[0].Value + + # Simple IPv4 REGEX + $IPv4 = [regex]::Matches($FritzBoxEvent[0], '(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)')[0].Value + + # Do we have a DATE in the event? + if ($EventDate -ne '') + { + # Transform the Event DATE + $EventEntry = $FritzBoxEvent[0].replace($EventDate, '') + + # Ensure we have the correct format, just in case + #$EventDate = (Get-Date -Date $EventDate) + } + + # Apply the Limit, if needed + if (($Filterhours) -and ($EventDate -ge $Filterhours)) + { + # Cleanup the event message (remove leading or trailing whitespaces) + $EventEntry = $EventEntry.trim() + + # Add the Event to the list + $FritzEvents += [PSCustomObject]@{ + Date = $EventDate + Message = $EventEntry + IPv4 = $IPv4 + IPv6 = $IPv6 + } + } + + # Cleanup + $EventDate = $null + $IPv6 = $null + $IPv4 = $null + $EventEntry = $null + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -WarningAction Continue + #endregion ErrorHandler + } + } + } + catch + { + # Cleanup + $FritzEvents = $null + $FritzBoxSecurePassword = $null + $FritzBoxLoginPage = $null + $FritzBoxEventPage = $null + $SecureStringToBSTR = $null + $PtrToStringAuto = $null + $ChallengeRequest = $null + $Challenge = $null + $Code1 = $null + $Code2 = $null + $SIDRequestBody = $null + $SIDRequest = $null + $SID = $null + $FritzBoxEvents = $null + $Hours = $null + $Filterhours = $null + + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + finally + { + # Garbage Collection + [GC]::Collect() + } + } + + end + { + # Dump to the Terminal + $FritzEvents + + # Cleanup + $FritzEvents = $null + $FritzBoxSecurePassword = $null + $FritzBoxLoginPage = $null + $FritzBoxEventPage = $null + $SecureStringToBSTR = $null + $PtrToStringAuto = $null + $ChallengeRequest = $null + $Challenge = $null + $Code1 = $null + $Code2 = $null + $SIDRequestBody = $null + $SIDRequest = $null + $SID = $null + $FritzBoxEvents = $null + $Hours = $null + $Filterhours = $null + + # Garbage Collection + [GC]::Collect() + } +} + +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Get-IPv6InWindows.ps1 b/Powershell/PowerShell-collection/Misc/Get-IPv6InWindows.ps1 new file mode 100644 index 0000000..b86c4c8 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-IPv6InWindows.ps1 @@ -0,0 +1,188 @@ +function Get-IPv6InWindows +{ + <# + .SYNOPSIS + Get the configured IPv6 value from the registry + + .DESCRIPTION + Get the configured IPv6 value from the registry + Transforms the Registry value into human understandable values + + .EXAMPLE + PS C:\> Get-IPv6InWindows + All IPv6 components are enabled (0) + + .EXAMPLE + PS C:\> Get-IPv6InWindows -verbose + Prefer IPv4 over IPv6 (32) + + Get the configured IPv6 value from the registry, with verbose output + + .LINK + Set-IPv6InWindows + + .LINK + https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows + + .LINK + https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows#reference + + .NOTES + Just a wrapper to make the values more human readable. + This is just a quick and dirty initial version! + + If you find any further values (other then the supported), please let me know! + + Want to modify your IPv6 configuration? Use its companion Set-IPv6InWindows + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([string])] + param () + + begin + { + # Cleanup + $ComponentValue = $null + $ComponentValueText = $null + + #region BoundParameters + if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + { + $IsVerbose = $true + } + else + { + $IsVerbose = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) + { + $IsDebug = $true + } + else + { + $IsDebug = $false + } + #endregion BoundParameters + } + + process + { + # Get the Value from the registry + try + { + $paramGetItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\tcpip6\Parameters' + Name = 'DisabledComponents' + Debug = $IsDebug + Verbose = $IsVerbose + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $ComponentValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty DisabledComponents -ErrorAction Stop -WarningAction Continue) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + Write-Verbose -Message $info + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + + switch ($ComponentValue) + { + 0 + { + $ComponentValueText = ('All IPv6 components are enabled ({0})' -f $ComponentValue) + } + 255 + { + $ComponentValueText = ('All IPv6 components are disabled ({0})' -f $ComponentValue) + } + 2 + { + $ComponentValueText = ('6to4 is disabled ({0})' -f $ComponentValue) + } + 4 + { + $ComponentValueText = ('ISATAP is disabled ({0})' -f $ComponentValue) + } + 8 + { + $ComponentValueText = ('Teredo is disabled ({0})' -f $ComponentValue) + } + 10 + { + $ComponentValueText = ('Teredo and 6to4 is disabled ({0})' -f $ComponentValue) + } + 1 + { + $ComponentValueText = ('All tunnel interfaces are disabled ({0})' -f $ComponentValue) + } + 16 + { + $ComponentValueText = ('All LAN and PPP interfaces are disabled ({0})' -f $ComponentValue) + } + 17 + { + $ComponentValueText = ('All LAN, PPP and tunnel interfaces are disabled ({0})' -f $ComponentValue) + } + 32 + { + $ComponentValueText = ('Prefer IPv4 over IPv6 ({0})' -f $ComponentValue) + } + default + { + $ComponentValueText = ('Unknown value found: {0}' -f $ComponentValue) + } + } + } + + end + { + # Dump the info + $ComponentValueText + } +} +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Get-IpInfo.ps1 b/Powershell/PowerShell-collection/Misc/Get-IpInfo.ps1 new file mode 100644 index 0000000..9ffdda9 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-IpInfo.ps1 @@ -0,0 +1,75 @@ +<# + .SYNOPSIS + Get all local IP addresses + + .DESCRIPTION + Get all local IP addresses, just the addresses + + .EXAMPLE + PS C:\> .\Get-IpInfo.ps1 + + Get all local IP addresses, just the addresses + + .NOTES + Quick an dirty function that uses Net.DNS to gather the information about the IP Addresses +#> +[CmdletBinding(ConfirmImpact = 'None')] +[OutputType([psobject])] +param () + +begin +{ + #Cleanup + $IpAddressInfo = $null +} + +process +{ + # Get the Info using Net.Dns + $IpAddressInfo = @( + (([Net.DNS]::GetHostAddresses([Net.Dns]::GetHostByName(($env:COMPUTERNAME)).HostName) | Where-Object -FilterScript { + $_.IsIPv6LinkLocal -eq $false + }).IPAddressToString | Where-Object -FilterScript { + $_ -ne '::1' + }) + ) +} + +end +{ + # Dump the Info + $IpAddressInfo + + #Cleanup + $IpAddressInfo = $null +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Get-LocalGroupMembership.ps1 b/Powershell/PowerShell-collection/Misc/Get-LocalGroupMembership.ps1 new file mode 100644 index 0000000..09d9049 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-LocalGroupMembership.ps1 @@ -0,0 +1,106 @@ +function Get-LocalGroupMembership +{ + <# + .SYNOPSIS + Get all local Groups a given User is a Member of + + .DESCRIPTION + The the the membership of all local Groups for a given User. + The Given User could be a local User (COMPUTER\USER) or a Domain User (DOMAIN\USER). + + .PARAMETER UserName + Given User could be a local User (COMPUTER\USER) or a Domain User (DOMAIN\USER). + Default is the user that executes the function. + + .EXAMPLE + PS C:\> Get-LocalGroupMembership + + Dump the Group Membership for the User that executes the function + + .EXAMPLE + PS C:\> Get-LocalGroupMembership -UserName 'CONTOSO\John.Doe' + + Dump the Group Membership for the User John.Doe in the Domain CONTOSO + + .EXAMPLE + PS C:\> Get-LocalGroupMembership -UserName "$env:COMPUTERNAME\John.Doe" + + Dump the Group Membership for the User John.Doe on the local computer + + .EXAMPLE + PS C:\> Get-LocalGroupMembership -UserName 'CONTOSO\John.Doe' | Foreach-Object { Add-LocalGroupMember -Group $_ -Member "$env:COMPUTERNAME\John.Doe" -ErrorAction SilentlyContinue } + + Clone the Group Membership from User John.Doe in the Domain CONTOSO to User John.Doe on the local computer + + .NOTES + This is just a quick and dirty solution for a problem I faced. (See last example) + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('User')] + [string] + $UserName = ("$env:USERDOMAIN" + '\' + "$env:USERNAME") + ) + + begin + { + # Create a new Object + $LocalGroupMembership = @() + } + + process + { + $AllGroups = (Get-LocalGroup -Name *) + + foreach ($LocalGroup in $AllGroups) + { + if (Get-LocalGroupMember -Group $LocalGroup.Name -ErrorAction SilentlyContinue | Where-Object -FilterScript { + $_.name -eq $UserName + }) + { + $LocalGroupMembership += $LocalGroup.Name + } + } + } + end + { + # Dump the object to the console + $LocalGroupMembership + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Get-LocalIpAddresses.ps1 b/Powershell/PowerShell-collection/Misc/Get-LocalIpAddresses.ps1 new file mode 100644 index 0000000..d0f3d80 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-LocalIpAddresses.ps1 @@ -0,0 +1,95 @@ +function Get-LocalIpAddresses +{ + <# + .SYNOPSIS + Print a string with all IP addresses + + .DESCRIPTION + Print a string with all IP addresses. Supports IPv4 and IPv6. + It filters IPv6 Link Local only addresses by default. + + .PARAMETER TargetName + Specifies the computers to test. Type the computer names or type IP addresses in IPv4 or IPv6 format. Wildcard characters are not permitted. The default is localhost. + + .PARAMETER IPv6LinkLocal + Retuns IPv6 Link Local only addresses? Off by default. + + .EXAMPLE + PS C:\> Get-LocalIpAddresses + Print a string with all local IP addresses + + .EXAMPLE + PS C:\> Get-LocalIpAddresses -TargetName 'mycomputer' + Print a string with all IP addresses for the computer 'mycomputer' + + .NOTES + TODO: Remove the -TargetName in the next release! Makes no sense (only IPv4 is returned) + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([string])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [string] + $TargetName = $env:COMPUTERNAME, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('IsIPv6LinkLocal')] + [switch] + $IPv6LinkLocal + ) + + begin + { + $IpInfo = $null + } + + process + { + $IpInfo = ($TargetName | ForEach-Object -Process { + (([Net.DNS]::GetHostAddresses([Net.Dns]::GetHostByName($_).HostName) | Where-Object -FilterScript { + $_.IsIPv6LinkLocal -eq $IPv6LinkLocal + }).IPAddressToString) + }) + } + + end + { + # Dump to the Console + $IpInfo + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Get-etLatestNuGetRelease.ps1 b/Powershell/PowerShell-collection/Misc/Get-etLatestNuGetRelease.ps1 new file mode 100644 index 0000000..619114a --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Get-etLatestNuGetRelease.ps1 @@ -0,0 +1,158 @@ +function Get-etLatestNuGetRelease +{ + <# + .SYNOPSIS + Get the latest published version of a given Module from a NuGet Repository + + .DESCRIPTION + Get the latest published version of a given PowerShell Module from a NuGet Repository + + .PARAMETER Project + Name of the Project, e.g. et.Office365 + + .PARAMETER Repository + NuGet Repository, default is the PowerShell Gallery + + .PARAMETER Version + Return a PowerShell Version String instead of a String + + .EXAMPLE + PS C:\> Get-etLatestNuGetRelease -Project 'et.Office365' + + Get the latest published version of a given Module from a NuGet Repository + + .EXAMPLE + PS C:\> Get-etLatestNuGetRelease -Project 'et.Office365' -version + + Get the latest published version of a given Module from a NuGet Repository, but as Version instead of a String + + .EXAMPLE + PS C:\> 'et.Office365' | Get-etLatestNuGetRelease + + Get the latest published version of a given Module from a NuGet Repository + + .NOTES + enabling Technology internal Build helper function + + .LINK + Get-etModuleVersion + + .LINK + Compare-enModuleVersions + + .LINK + Find-Module + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([string])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Name of the Project, e.g. et.Office365')] + [ValidateNotNullOrEmpty()] + [Alias('etProject')] + [string] + $Project, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [ValidateNotNullOrEmpty()] + [Alias('etRepository', 'Gallery', 'NuGetGallery')] + [string] + $Repository = 'PSGallery', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 3)] + [Alias('enVersion')] + [switch] + $Version = $false + ) + + begin + { + $LatestNuGetRelease = $null + } + + process + { + try + { + $paramFindModule = @{ + Name = $Project + Repository = $Repository + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $LatestNuGetRelease = (Find-Module @paramFindModule | Select-Object -ExpandProperty Version) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -TargetObject ($info.Target) -ErrorAction Stop + break + } + } + + end + { + if ($Version) + { + [version]$LatestNuGetRelease = $LatestNuGetRelease + } + else + { + [string]$LatestNuGetRelease = $LatestNuGetRelease + } + + # Dump to the console + $LatestNuGetRelease + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Grant-LogOnAsService.ps1 b/Powershell/PowerShell-collection/Misc/Grant-LogOnAsService.ps1 new file mode 100644 index 0000000..7306662 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Grant-LogOnAsService.ps1 @@ -0,0 +1,131 @@ +function Grant-LogOnAsService +{ + <# + .SYNOPSIS + Grant user log on as a service right in PowerShell + + .DESCRIPTION + Grant user log on as a service right in PowerShell + + .PARAMETER Users + The User that should get the grant + + .INPUTS + String, Multi Value is OK here + + .OUTPUTS + None + + .EXAMPLE + PS C:\> Grant-LogOnAsService -Users 'johndoe' + + Grant user log on as a service right in PowerShell + + .LINK + https://gist.github.com/ned1313/9143039 + + .NOTES + Just a minor refactoring of the original + #> + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'The User that should get the grant')] + [ValidateNotNullOrEmpty()] + [string[]] + $Users + ) + + process + { + if ($pscmdlet.ShouldProcess('Apply login as a service', "$Users")) + { + # Get list of currently used SIDs + & "$env:windir\system32\secedit.exe" /export /cfg tempexport.inf + $curSIDs = (Select-String -Path .\tempexport.inf -Pattern 'SeServiceLogonRight') + $Sids = $curSIDs.line + $sidstring = '' + + foreach ($user in $Users) + { + $objUser = (New-Object -TypeName System.Security.Principal.NTAccount -ArgumentList ($user)) + $strSID = $objUser.Translate([Security.Principal.SecurityIdentifier]) + + if (!$Sids.Contains($strSID) -and !$Sids.Contains($user)) + { + $sidstring += ",*$strSID" + } + } + + if ($sidstring) + { + $newSids = $Sids + $sidstring + + Write-Output -InputObject ('New Sids: {0}' -f $newSids) + $tempinf = (Get-Content -Path tempexport.inf) + $tempinf = $tempinf.Replace($Sids, $newSids) + $null = (Add-Content -Path tempimport.inf -Value $tempinf -Force -Confirm:$false) + + & "$env:windir\system32\secedit.exe" /import /db secedit.sdb /cfg '.\tempimport.inf' + & "$env:windir\system32\secedit.exe" /configure /db secedit.sdb + & "$env:windir\system32\gpupdate.exe" /force + } + else + { + Write-Output -InputObject 'No new sids' + } + } + } + + end + { + if ($pscmdlet.ShouldProcess('Cleanup', 'Tempfiles')) + { + # Splat the Defaults + $paramRemoveItem = @{ + Force = $true + Confirm = $false + ErrorAction = 'SilentlyContinue' + } + + $null = (Remove-Item -Path '.\tempimport.inf' @paramRemoveItem) + $null = (Remove-Item -Path '.\secedit.sdb' @paramRemoveItem) + $null = (Remove-Item -Path '.\tempexport.inf' @paramRemoveItem) + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Hosts_helper.ps1 b/Powershell/PowerShell-collection/Misc/Hosts_helper.ps1 new file mode 100644 index 0000000..7ffc7e5 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Hosts_helper.ps1 @@ -0,0 +1,439 @@ +function Add-HostsEntry +{ + <# + .SYNOPSIS + Add a single Hosts Entry to the HOSTS File + + .DESCRIPTION + Add a single Hosts Entry to the HOSTS File, multiple are not supported yet! + + .PARAMETER Path + The path to the hosts file where the entry should be set. Defaults to the local computer's hosts file. + + .PARAMETER Address + The Address address for the hosts entry. + + .PARAMETER HostName + The hostname for the hosts entry. + + .PARAMETER force + Force (replace) + + .EXAMPLE + PS C:\> Add-HostsEntry -Address '0.0.0.0' -HostName 'badhost' + + Add the host 'badhost' with the Adress '0.0.0.0' (blackhole) wo the Hosts. + If an Entry for 'badhost' exists, the new one will be appended anyway (You end up with two entries) + + .EXAMPLE + PS C:\> Add-HostsEntry -Address '0.0.0.0' -HostName 'badhost' -force + + Add the host 'badhost' with the Adress '0.0.0.0' (blackhole) wo the Hosts. + If an Entry for 'badhost' exists, the new one will replace the existing one. + + .NOTES + Internal Helper, inspired by an old GIST I found + + .LINK + Get-HostsFile + + .LINK + Remove-HostsEntry + + .LINK + https://gist.github.com/markembling/173887/1824b370be3fe468faceaed5f39b12bad010a417 + #> + [CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + Position = 0, + HelpMessage = 'The IP address for the hosts entry.')] + [ValidateNotNullOrEmpty()] + [Alias('ipaddress', 'ip')] + [string] + $Address, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'The hostname for the hosts entry.')] + [ValidateNotNullOrEmpty()] + [Alias('Host', 'Name')] + [string] + $HostName, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 3)] + [switch] + $force = $false, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [ValidateNotNullOrEmpty()] + [Alias('filename', 'Hosts', 'hostsfile', 'file')] + [string] + $Path = "$env:windir\System32\drivers\etc\hosts" + ) + begin + { + Write-Verbose -Message 'Start' + } + + process + { + if ($force) + { + try + { + $null = (Remove-HostsEntry -HostName $HostName -Path $Path -ErrorAction SilentlyContinue -WarningAction SilentlyContinue) + } + catch + { + Write-Verbose -Message 'Looks like the entry was not there before' + } + } + + try + { + if ($pscmdlet.ShouldProcess('Target', 'Operation')) + { + # Get a clean (end of) file + $paramGetContent = @{ + Path = $Path + Raw = $true + Force = $true + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $HostsFileContent = (((Get-Content @paramGetContent ).TrimEnd()).ToString()) + + $NewValue = "`n" + $Address + "`t`t" + $HostName + $NewHostsFileContent = $HostsFileContent + $NewValue + + $paramSetContent = @{ + Path = $Path + Value = $NewHostsFileContent + Force = $true + Confirm = $false + Encoding = 'UTF8' + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $null = (Set-Content @paramSetContent) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + } + } + + end + { + Write-Verbose -Message 'Done' + } +} + +function Remove-HostsEntry +{ + <# + .SYNOPSIS + Removes a single Hosts Entry from the HOSTS File + + .DESCRIPTION + Removes a single Hosts Entry from the HOSTS File, multiple are not supported yet! + + .PARAMETER Path + The path to the hosts file where the entry should be set. Defaults to the local computer's hosts file. + + .PARAMETER HostName + The hostname for the hosts entry. + + .EXAMPLE + PS C:\> Remove-HostsEntry -HostName 'Dummy' + + Remove the entry for the host 'Dummy' from the HOSTS File + + .NOTES + Internal Helper, inspired by an old GIST I found + + .LINK + Get-HostsFile + + .LINK + Add-HostsEntry + + .LINK + https://gist.github.com/markembling/173887/1824b370be3fe468faceaed5f39b12bad010a417 + #> + [CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'The hostname for the hosts entry.')] + [ValidateNotNullOrEmpty()] + [Alias('Host', 'Name')] + [string] + $HostName, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [Alias('Hosts', 'hostsfile', 'file', 'Filename')] + [string] + $Path = "$env:windir\System32\drivers\etc\hosts" + ) + + begin + { + Write-Verbose -Message 'Start' + + try + { + $paramGetContent = @{ + Path = $Path + Raw = $true + Force = $true + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $HostsFileContent = (((Get-Content @paramGetContent ).TrimEnd()).ToString()) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + } + + $newLines = @() + } + + process + { + foreach ($line in $HostsFileContent) + { + $bits = [regex]::Split($line, '\t+') + if ($bits.count -eq 2) + { + if ($bits[1] -ne $HostName) + { + $newLines += $line + } + } + else + { + $newLines += $line + } + } + + # Write file + try + { + if ($pscmdlet.ShouldProcess('Target', 'Operation')) + { + $paramClearContent = @{ + Path = $Path + Force = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $null = (Clear-Content @paramClearContent) + + $paramSetContent = @{ + Path = $Path + Value = $newLines + Force = $true + Confirm = $false + Encoding = 'UTF8' + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $null = (Set-Content @paramSetContent) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + } + } + + end + { + Write-Verbose -Message 'Done' + } +} + +function Get-HostsFile +{ + <# + .SYNOPSIS + Print the HOSTS File in a more clean format + + .DESCRIPTION + Print the HOSTS File in a more clean format + + .PARAMETER Path + The path to the hosts file where the entry should be set. Defaults to the local computer's hosts file. + + .PARAMETER raw + Print raw Hosts File + + .EXAMPLE + PS C:\> Get-HostsFile + + Print the HOSTS File in a more clean format + + .EXAMPLE + PS C:\> Get-HostsFile -raw + + Print the HOSTS File in the regular format + + .NOTES + Internal Helper, inspired by an old GIST I found + + .LINK + Add-HostsEntry + + .LINK + Remove-HostsEntry + + .LINK + https://gist.github.com/markembling/173887/1824b370be3fe468faceaed5f39b12bad010a417 + #> + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [Alias('Hosts', 'hostsfile', 'file', 'filename')] + [string] + $Path = "$env:windir\System32\drivers\etc\hosts", + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('plain')] + [switch] + $raw = $false + ) + + begin + { + $HostsFileContent = Get-Content -Path $Path + } + + process + { + foreach ($line in $HostsFileContent) + { + if ($raw) + { + Write-Output -InputObject $line + } + else + { + $bits = [regex]::Split($line, '\t+') + if ($bits.count -eq 2) + { + [string]$HostsFileLine = $bits + + if (-not ($HostsFileLine.StartsWith('#'))) + { + Write-Output -InputObject $HostsFileLine + } + } + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Install-DSCResourceKit.ps1 b/Powershell/PowerShell-collection/Misc/Install-DSCResourceKit.ps1 new file mode 100644 index 0000000..fe3c054 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Install-DSCResourceKit.ps1 @@ -0,0 +1,183 @@ +function Install-DSCResourceKit +{ + <# + .SYNOPSIS + Install the complete PowerShell DSCResourceKit + + .DESCRIPTION + Install the complete PowerShell DSCResourceKit from the PowerShell Gallery. + It only installs the missing resources. + + .PARAMETER Scope + Specifies the installation scope of the module. The acceptable values for this parameter are: AllUsers and CurrentUser. + + The AllUsers scope lets modules be installed in a location that is accessible to all users of the computer, that is, %systemdrive%:\ProgramFiles\WindowsPowerShell\Modules. + + The CurrentUser scope lets modules be installed only to $home\Documents\WindowsPowerShell\Modules, so that the module is available only to the current user. + + .EXAMPLE + PS C:\> Install-DSCResourceKit + + Install the complete PowerShell DSCResourceKit + + .EXAMPLE + PS C:\> Install-DSCResourceKit -verbose + + Install the complete PowerShell DSCResourceKit + + .NOTES + Releasenotes: + 1.0.0 2019-04-10: Internal Release + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + PowerShellGet + + .LINK + https://aka.ms/InstallModule + + .LINK + https://www.powershellgallery.com + #> + [CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateSet('AllUsers', 'CurrentUser', IgnoreCase = $true)] + [Alias('ModuleScope')] + [String] + $Scope = 'AllUsers' + ) + + begin + { + try + { + if (-not ($Scope)) + { + $Scope = 'AllUsers' + } + + $AllReSources = ((Find-Module -Tag DSCResourceKit).name) + $AllInstall = ((Get-Module -ListAvailable).Name) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + # Whoops + Write-Error -Message $info.Exception -ErrorAction Stop + } + } + + process + { + if ($pscmdlet.ShouldProcess('DSCResourceKit', 'Install')) + { + foreach ($DSCResource in $AllReSources) + { + if (-not ($AllInstall.Contains($DSCResource))) + { + try + { + Write-Verbose -Message ('Try to install {0}' -f $DSCResource) + + $paramInstallModule = @{ + Name = $DSCResource + Scope = $Scope + AllowClobber = $true + SkipPublisherCheck = $true + Repository = 'PSGallery' + Force = $true + ErrorAction = 'Stop' + } + $null = (Install-Module @paramInstallModule) + + Write-Verbose -Message ('Installed {0}' -f $DSCResource) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Warning -Message ('Unable to install {0}' -f $DSCResource) -ErrorAction Continue -WarningAction Continue + + # Cleanup + $e = $null + $info = $null + } + } + else + { + Write-Verbose -Message ('{0} is already installed' -f $DSCResource) + } + } + } + } + + end + { + # Cleanup + $AllReSources = $null + $AllInstall = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Invoke-CheckPowerShellModules.ps1 b/Powershell/PowerShell-collection/Misc/Invoke-CheckPowerShellModules.ps1 new file mode 100644 index 0000000..3e5db08 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Invoke-CheckPowerShellModules.ps1 @@ -0,0 +1,360 @@ +function Invoke-CheckPowerShellModules +{ + <# + .SYNOPSIS + Check if one or more given modules are installed. + + .DESCRIPTION + Check if one or more given modules are installed. + Any missing modules can be installed (optional) and updated to the latest version available on the PowerShell Gallery can be applied (optional). + + .PARAMETER Module + One or more modules to check, update, install. + + .PARAMETER Install + Install any missing modules from the PowerShell Gallery? + + .PARAMETER Update + Updated to the latest PowerShell Gallery Version of the module, if available? + + .PARAMETER Scope + Specifies the installation scope of the module. + The acceptable values for this parameter are: AllUsers and CurrentUser. + The default is CurrentUser. + + The AllUsers scope lets modules be installed in a location that is accessible to all users of the computer, + that is, %systemdrive%:\ProgramFiles\WindowsPowerShell\Modules. Elevated Shell required! + + The CurrentUser scope lets modules be installed only to $home\Documents\WindowsPowerShell\Modules, + so that the module is available only to the current user. + + .EXAMPLE + PS C:\> Invoke-CheckPowerShellModules -Module 'MSOnline', 'azuread', 'AzureADPreview', 'Microsoft.Online.SharePoint.PowerShell', 'MicrosoftTeams', 'Microsoft.PowerApps.PowerShell', 'Microsoft.PowerApps.Administration.PowerShell', 'SharePointPnPPowerShellOnline', 'credentialmanager' -Install + + Check if all the Office 365 related PowerShell Modules are installed. + This will not install anything missing; it just runs a check! + + .EXAMPLE + PS C:\> Invoke-CheckPowerShellModules -Module 'MSOnline', 'azuread', 'AzureADPreview', 'Microsoft.Online.SharePoint.PowerShell', 'MicrosoftTeams', 'Microsoft.PowerApps.PowerShell', 'Microsoft.PowerApps.Administration.PowerShell', 'SharePointPnPPowerShellOnline', 'credentialmanager' -Install + + Install all the Office 365 related PowerShell Modules if anything is missing. + + .EXAMPLE + PS C:\> Invoke-CheckPowerShellModules -Module 'MSOnline', 'azuread', 'AzureADPreview', 'Microsoft.Online.SharePoint.PowerShell', 'MicrosoftTeams', 'Microsoft.PowerApps.PowerShell', 'Microsoft.PowerApps.Administration.PowerShell', 'SharePointPnPPowerShellOnline', 'credentialmanager' -Scope AllUsers + + Install all the Office 365 related PowerShell Modules if anything is missing (system wide). + This required to runn in an elevated Shell!!! + + .EXAMPLE + PS C:\> Invoke-CheckPowerShellModules -Module 'MSOnline', 'azuread', 'AzureADPreview', 'Microsoft.Online.SharePoint.PowerShell', 'MicrosoftTeams', 'Microsoft.PowerApps.PowerShell', 'Microsoft.PowerApps.Administration.PowerShell', 'SharePointPnPPowerShellOnline', 'credentialmanager' -Update + + Install all the Office 365 related PowerShell Modules if missing, automatically updates the latest version (if there is any update available) + + .NOTES + For now, only the PowerShell Gallery is supported as Repository! + The next version might bring the check for an elevated shell if the scope is set to 'AllUsers'. + + Releasenotes: + 1.0.1 2019-05-24: Make it a bit more robust and add some examples (intial public release) + 1.0.0 2019-05-15: Initial Release (internal) + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + #> + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'One or more Modules to check.')] + [ValidateNotNullOrEmpty()] + [string[]] + $Module, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('AutoInstall', 'InstallMissing')] + [switch] + $Install = $null, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [Alias('AutoUpdate')] + [switch] + $Update = $null, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 3)] + [ValidateNotNullOrEmpty()] + [ValidateSet('AllUsers', 'CurrentUser', IgnoreCase = $true)] + [Alias('InstallScope', 'ModuleScope')] + [string] + $Scope = 'CurrentUser' + ) + + begin + { + # The default scope is the current user (if not given) + if (-not $Scope) + { + $Scope = 'CurrentUser' + } + + # Mandatory PowerShell Modules for Office 365 administration. + if (-not $Module) + { + $Module = 'MSOnline', 'azuread', 'AzureADPreview', 'Microsoft.Online.SharePoint.PowerShell', 'MicrosoftTeams', 'Microsoft.PowerApps.PowerShell', 'Microsoft.PowerApps.Administration.PowerShell' + } + } + + process + { + foreach ($PowerShellModule in $Module) + { + # Cleanup + $InstalledModuleVersion = $null + $LatestModuleVersion = $null + $UpdateVersion = $null + + try + { + Write-Verbose -Message ('Start processing for {0}' -f $PowerShellModule) + + # Cleanup + $InstalledModuleVersion = $null + + # In some cases, we might have different versions installed. + # We just want to have the latest and greatest one. + $paramGetModule = @{ + Name = $PowerShellModule + ListAvailable = $true + ErrorAction = 'Stop' + } + $InstalledModuleVersion = (Get-Module @paramGetModule | Select-Object -Property Name, Version, repositorysourcelocation | Sort-Object -Property Version -Descending | Select-Object -First 1) + + if (-not $InstalledModuleVersion) + { + if ($Install) + { + Write-Verbose -Message ('Start the installation of {0}' -f $PowerShellModule) + + try + { + if ($pscmdlet.ShouldProcess($PowerShellModule, 'Install')) + { + $paramInstallModule = @{ + Name = $PowerShellModule + Repository = 'PSGallery' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Scope = $Scope + Force = $true + AllowClobber = $true + } + $null = (Install-Module @paramInstallModule) + } + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Build the Info object + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose things + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + + Write-Verbose -Message ('Finished the installation of {0}' -f $PowerShellModule) + } + else + { + # Error message + Write-Error -Message ('{0} was not found...' -f $PowerShellModule) -Category NotInstalled -ErrorAction Stop + } + } + else + { + if ($InstalledModuleVersion.RepositorySourceLocation.Authority -ne 'www.powershellgallery.com') + { + Write-Error -Message ('Sorry, but only modules from the PowerShell Gallery are supported and {0} is not installed from there.' -f $PowerShellModule) -Category InvalidType -ErrorAction Stop + } + else + { + try + { + Write-Verbose -Message ('Get the latest PowerShell Gallery version for {0}' -f $PowerShellModule) + + $paramFindModule = @{ + Name = $PowerShellModule + Repository = 'PSGallery' + ErrorAction = 'Stop' + } + $LatestModuleVersion = (Find-Module @paramFindModule | Select-Object -Property Name, Version) + + $UpdateVersion = $LatestModuleVersion.Version + + Write-Verbose -Message ('Found version {0} of {1} in the PowerShell Gallery' -f $UpdateVersion, $PowerShellModule) + + if ($InstalledModuleVersion.Version -ilt $UpdateVersion) + { + Write-Verbose -Message ('Version {0} for {1} is availible in the PowerShell Galery' -f $UpdateVersion, $PowerShellModule) + + if ($Update) + { + Write-Verbose -Message ('Start the update for {0} to version {1}' -f $PowerShellModule, $UpdateVersion) + + try + { + if ($pscmdlet.ShouldProcess($PowerShellModule, 'Update')) + { + $paramInstallModule = @{ + Name = $PowerShellModule + Repository = 'PSGallery' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Scope = $Scope + Force = $true + AllowClobber = $true + } + $null = (Install-Module @paramInstallModule) + } + + Write-Verbose -Message ('Installed version {0} for {1}' -f $UpdateVersion, $PowerShellModule) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Create the Info Object + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message + } + } + else + { + Write-Warning -Message ('Version {0} for {1} is availible on the PowerShell Galery' -f $UpdateVersion, $PowerShellModule) + } + } + else + { + Write-Verbose -Message ('No update found for {0}' -f $PowerShellModule) + } + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Create the Info Object + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message + } + } + } + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Create the Info Object + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + } + } + + end + { + Write-Verbose -Message 'Done' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Invoke-CleanupOldGalleryModuleVersions.ps1 b/Powershell/PowerShell-collection/Misc/Invoke-CleanupOldGalleryModuleVersions.ps1 new file mode 100644 index 0000000..32f7a46 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Invoke-CleanupOldGalleryModuleVersions.ps1 @@ -0,0 +1,269 @@ +#requires -Version 3.0 -Modules @{ ModuleName="PowerShellGet"; ModuleVersion="2.0.0" } -RunAsAdministrator + +<# + .SYNOPSIS + Remove older versions of a installed PowerShell module + + .DESCRIPTION + Remove older versions of a installed PowerShell module + + .EXAMPLE + PS C:\> .\Invoke-CleanupOldGalleryModuleVersions.ps1 + + .EXAMPLE + PS C:\> .\Invoke-CleanupOldGalleryModuleVersions.ps1 -Verbose + + .EXAMPLE + PS C:\> .\Invoke-CleanupOldGalleryModuleVersions.ps1 -Verbose + + .EXAMPLE + PS C:\> .\Invoke-CleanupOldGalleryModuleVersions.ps1 -debug + + .NOTES + This is a replacement for some older functions + + .LINK + Invoke-UpdateAllGalleryModules.ps1 +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + #region Defaults + $STP = 'Stop' + $CNT = 'Continue' + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region Cleanup + $AllModules = $null + #endregion Cleanup + + #region BoundParameters + if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + { + $VerboseValue = $true + } + else + { + $VerboseValue = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) + { + $DebugValue = $true + } + else + { + $DebugValue = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['WhatIf']).IsPresent) + { + $WhatIfValue = $true + } + else + { + $WhatIfValue = $false + } + #endregion BoundParameters +} + +process +{ + # Get the Module information + $paramGetModule = @{ + ListAvailable = $true + Refresh = $true + ErrorAction = $CNT + WarningAction = $CNT + Verbose = $VerboseValue + Debug = $DebugValue + } + $AllModules = (Get-Module @paramGetModule | Where-Object -FilterScript { + $_.RepositorySourceLocation -like '*powershellgallery*' + } | Select-Object -ExpandProperty Name) + + $AllModules = ($AllModules | Sort-Object -Unique) + + foreach ($ModuleName in $AllModules) + { + Write-Verbose -Message ('Get all existing versions of {0}' -f $ModuleName) + + $AllModuleVersions = $null + $AllModuleVersions = (Get-InstalledModule -Name $ModuleName -AllVersions -ErrorAction $SCT -WarningAction $CNT) + + if (((($AllModuleVersions).Version).count) -gt 1) + { + $LatestModuleVersion = $null + + $LatestModuleVersion = (($AllModuleVersions | Sort-Object -Property $AllModuleVersions.Version)[1]) + + try + { + $output = $null + $output = ($AllModuleVersions | Where-Object { + (($_.Version) -lt ($LatestModuleVersion.Version)) + } | ForEach-Object -Process { + Write-Verbose -Message ('Start to process {0}' -f ($_).Name) + + try + { + $paramUninstallModule = @{ + Name = $_ + Force = $true + Confirm = $false + WhatIf = $WhatIfValue + Verbose = $VerboseValue + Debug = $DebugValue + ErrorAction = $STP + WarningAction = $CNT + } + Uninstall-Module @paramUninstallModule + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $CNT + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + finally + { + if (Test-Path -Path $_.InstalledLocation -ErrorAction $SCT -WarningAction $SCT) + { + Write-Verbose -Message ('Try to remove {0}' -f ($_).InstalledLocation) + + try + { + $paramRemoveItem = @{ + Path = $_.InstalledLocation + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $CNT + WhatIf = $WhatIfValue + Verbose = $VerboseValue + Debug = $DebugValue + } + Remove-Item @paramRemoveItem + + Write-Verbose -Message ('Removed {0}' -f ($_).InstalledLocation) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + } + } + + Write-Verbose -Message ('Removed old versions off {0}' -f ($_).Name) + }) + $output + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message ('Failed to process {0}' -f ($_).Name) + } + } + else + { + Write-Verbose -Message ('Skip {0}' -f ($AllModuleVersions).Name) + } + } +} + +end +{ + $AllModules = $null +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Invoke-CloudFlareDDNSUpdate.ps1 b/Powershell/PowerShell-collection/Misc/Invoke-CloudFlareDDNSUpdate.ps1 new file mode 100644 index 0000000..bb9cd41 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Invoke-CloudFlareDDNSUpdate.ps1 @@ -0,0 +1,302 @@ +#requires -Version 3.0 -Modules DnsClient + +<# + .SYNOPSIS + Update CloudFlare DNS A Record if needed + + .DESCRIPTION + Update CloudFlare DNS A Record if needed + + The prevent to much API calls, we use a regular DNS query first. + Only if this query spot a difference, we ensure if an update is needed by ask the Cloudflare API for the latest published info. + If there is stiff a difference, the cmdlet will update the entry for you. + + If you use a new/unknown hostname in the CF_HOSTNAME parameter, the cmdlet will create a new entry for the given host! + + .PARAMETER CF_TOKEN + CloudFlare API Token + + Hint: You can find your API key at: https://dash.cloudflare.com/profile/api-tokens + + Create a dedicated Token just for this cmdlet and give it a name that indicate the purpose of it + + The Token needs a least the following permission: Zone.Zone, Zone.DNS + The token needs access to at least the Zone you want to update (Resources), or use 'All zones' + + .PARAMETER CF_DOMAIN + The CloudFlare DNS zone you want to modify + + Example: contoso.com (this is also the default) + + .PARAMETER CF_HOSTNAME + This is the A record you'd like to update or add + + Example: homelab (this is also the default) + + Please Note: We support A Records only at this time! + + .PARAMETER DNSServer + Resolves hostname using DNS instead of checking CloudFlare. + It is recommended to use the CloudFlare DNS Servers, e.g. 1.1.1.1 + You can use any other server, but mind that you might not see the changed IP until the Cache TTL expired on this Server! + + .EXAMPLE + PS C:\> .\Invoke-CloudFlareDDNSUpdate.ps1 -CF_TOKEN '' -CF_DOMAIN 'contoso.com' -CF_HOSTNAME 'homelab' + + Check and updates the host 'homelab' in the DNS Zone 'contoso.com' + + .EXAMPLE + PS C:\> .\Invoke-CloudFlareDDNSUpdate.ps1 -CF_TOKEN '' -CF_DOMAIN 'contoso.com' -CF_HOSTNAME 'homelab' -Verbose + + Check and updates the host 'homelab' in the DNS Zone 'contoso.com', but run in verbose mode + + .EXAMPLE + PS C:\> .\Invoke-CloudFlareDDNSUpdate.ps1 -CF_TOKEN '' -CF_DOMAIN 'contoso.com' -CF_HOSTNAME 'homelab' -DNSServer 1.0.0.1 + + Check and updates the host 'homelab' in the DNS Zone 'contoso.com', uses the backup CloudFlare DNS to get the published info + + .LINK + https://1.1.1.1/dns/ + + .NOTES + We use a regular (cheap) DNS call to reduce the number of calls to CloudFlare (they allow 200 reqs/minute but why ask an API first?) + + There is no output by the cmdlet, makes it easier if run a a service or schedules task. use the -Verbose switch to see what the cmdlet is doing + + Please Note: We support A Records only at this time! We are already testing IPv6 (AAAA) and a few others. +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('CLOUDFLARE_TOKEN', 'CFAPIKey', 'Token')] + [string] + $CF_TOKEN = '', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('CLOUDFLARE_Domain', 'CLOUDFLARE_DomainName', 'CFDomainName', 'Zone')] + [string] + $CF_DOMAIN = 'contoso.com', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('CFARecord', 'CLOUDFLARE_HOST', 'CLOUDFLARE_HOSTNAME')] + [string] + $CF_HOSTNAME = 'homelab', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('DNSToUse')] + [string] + $DNSServer = '1.1.1.1' +) + +begin +{ + #region Cleanup + $CF_KnownIP = $null + $CF_ExternalIP = $null + #endregion Cleanup + + #region CheapRequests + if (Get-Command -Name Resolve-DnsName -ErrorAction SilentlyContinue) + { + # Get the A record from the CloudFlare DNS (cheap request) + $paramResolveDnsName = @{ + Name = ($CF_HOSTNAME + '.' + $CF_DOMAIN) + Type = 'A' + Server = $DNSServer + ErrorAction = 'SilentlyContinue' + WarningAction = 'Continue' + } + [string]$CF_KnownIP = (((Resolve-DnsName @paramResolveDnsName) | Select-Object -ExpandProperty IPAddress).Trim()) + } + elseif (Get-Command -Name dig -ErrorAction SilentlyContinue) + { + # This is the Fallback on macOS, due to the missing DnsClient module on PowerShell core here + [string]$CF_KnownIP = (((dig A ($CF_HOSTNAME + '.' + $CF_DOMAIN) ('@' + $DNSServer) +short)).Trim()) + } + else + { + Write-Warning -Message 'Unable to lookup the DNS entry, we try to use the CloudFlare API' -WarningAction Continue + + # Set a dummy (to prevent any null pointer exception during the compare) + [string]$CF_KnownIP = '0.0.0.0' + } + + # Get the external IP via Web Request from our own service (cheap request) + $paramInvokeRestMethod = @{ + Method = 'Get' + UseBasicParsing = $true + Uri = 'https://ip.enatec.net' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + [string]$CF_ExternalIP = ((Invoke-RestMethod @paramInvokeRestMethod).Trim()) + #endregion CheapRequests +} + +process +{ + # Compare the two values + if ($CF_ExternalIP -ne $CF_KnownIP) + { + # Looks like there is a Difference + + # Only the V4 API is supported by the cmdlet yet! + $CF_API_ENDPOINT = $null + $CF_API_ENDPOINT = 'https://api.cloudflare.com/client/v4' + + $CF_Headers = $null + $CF_Headers = @{ + 'Authorization' = ('Bearer ' + $CF_TOKEN) + 'Content-Type' = 'application/json' + } + + $CF_ZoneURI = $null + $CF_ZoneURI = ($CF_API_ENDPOINT + '/zones?name=' + $CF_DOMAIN) + + Write-Verbose -Message ('Getting DNS-Zone ID for ' + $($CF_DOMAIN) + ' via ' + $CF_ZoneURI) + + # Let us get the Zone Info directly from CloudFlare (API Request) + $CF_ZoneId = $null + $paramInvokeRestMethod = @{ + Uri = $CF_ZoneURI + ContentType = 'application/json' + Headers = $CF_Headers + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $CF_ZoneId = (((Invoke-RestMethod @paramInvokeRestMethod).result).id) + + $CF_DNSURI = $null + $CF_DNSURI = ($CF_API_ENDPOINT + '/zones/' + $CF_ZoneId + '/dns_records?type=A&name=' + $CF_HOSTNAME + '.' + $CF_DOMAIN) + + Write-Verbose -Message ('Getting DNS data for ' + $($CF_HOSTNAME).$($CF_DOMAIN) + ' via ' + $CF_DNSURI) + + # Let us get the host Info directly from CloudFlare (API Request) + $CF_DNSData = $null + $paramInvokeRestMethod = @{ + Uri = $CF_DNSURI + ContentType = 'application/json' + Headers = $CF_Headers + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $CF_DNSData = ((Invoke-RestMethod @paramInvokeRestMethod).result) + + # Compare again (Double check) + if ($CF_ExternalIP -ne $CF_DNSData.content) + { + # OK, we are sure that there is a new IP! + Write-Verbose -Message 'IP address change detected, we will try to update the CloudFlare DNS' + + try + { + $CF_Body = $null + $CF_Body = @{ + 'type' = 'A' + 'name' = ($CF_HOSTNAME + '.' + $CF_DOMAIN) + 'content' = $CF_ExternalIP + 'ttl' = '1' + } + + $URI_Update = $null + $URI_Update = ($CF_API_ENDPOINT + '/zones/' + $CF_ZoneId + '/dns_records/' + $($CF_DNSData.id)) + + # Apply the new IP address to the CloudFlare DNS + $CF_Result = $null + $paramInvokeRestMethod = @{ + Uri = $URI_Update + Method = 'Put' + ContentType = 'application/json' + Headers = $CF_Headers + Body = $ + WebSession = ($CF_Body | ConvertTo-Json) + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $CF_Result = ((Invoke-RestMethod @paramInvokeRestMethod).result) + + if ($CF_Result.content -eq $CF_ExternalIP) + { + Write-Verbose -Message 'SUCCESS: CloudFlare DNS was successfully updated' + } + else + { + Write-Verbose -Message 'FAILED: CloudFlare DNS was not successfully updated' + } + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Just in case + exit 1 + } + } + else + { + Write-Verbose -Message 'CloudFlare: No update is needed' + } + } + else + { + Write-Verbose -Message 'DNS: No update is needed' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Invoke-DSCPerfReqConfigCheck.ps1 b/Powershell/PowerShell-collection/Misc/Invoke-DSCPerfReqConfigCheck.ps1 new file mode 100644 index 0000000..dad2897 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Invoke-DSCPerfReqConfigCheck.ps1 @@ -0,0 +1,159 @@ +function Invoke-DSCPerfReqConfigCheck +{ + <# + .SYNOPSIS + Perform Required Configuration Checks and suppress all outputs. + + .DESCRIPTION + Run the DSCLocalConfigurationManager method PerformRequiredConfigurationChecks. + + .PARAMETER Silent + The progress bar will be suppressed. this is not the case by default. + + .EXAMPLE + PS C:\> Invoke-DSCPerfReqConfigCheck + True + + # Run without any error + + .EXAMPLE + PS C:\> Invoke-DSCPerfReqConfigCheck -Silent + True + + # Run without any error. Suppress the progress bar. + + .EXAMPLE + PS C:\> Invoke-DSCPerfReqConfigCheck + False + + # The run had errors. + + .EXAMPLE + PS C:\> Invoke-DSCPerfReqConfigCheck -Silent + False + + # The run had errors. Suppress the progress bar. + + .NOTES + I do a lot of testing with several DSC configurations. + I just want a TRUE or FALSE as return to see if its working, or not. + You may guess why: I use this in a CI chain :-) + + You may want to have separated EventLog entries for DSC (useful for the log-Resource): + & "$env:windir\system32\wevtutil.exe" set-log 'Microsoft-Windows-Dsc/Analytic' /q:true /e:true + & "$env:windir\system32\wevtutil.exe" set-log 'Microsoft-Windows-Dsc/Debug' /q:True /e:true + + I dedicate any and all copyright interest in this software to the public domain. + I make this dedication for the benefit of the public at large and to the detriment of my heirs and successors. + I intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. + + .LINK + Author http://jhochwald.com + + .LINK + LICENSE http://unlicense.org + + .LINK + Invoke-CimMethod + Write-Verbose + Get-WinEvent + #> + [OutputType([bool])] + param + ( + [Parameter(ValueFromPipeline, + Position = 1)] + [switch] + $Silent = $null + ) + + begin + { + $SC = 'SilentlyContinue' + + if ($Silent) + { + $ProgressPreference = $SC + } + } + + process + { + $InvokeCimMethodParams = @{ + Namespace = 'root/Microsoft/Windows/DesiredStateConfiguration' + ClassName = 'MSFT_DSCLocalConfigurationManager' + MethodName = 'PerformRequiredConfigurationChecks' + Arguments = @{ + Flags = [uint32] 1 + } + ErrorAction = $SC + WarningAction = $SC + } + + try + { + $null = (Invoke-CimMethod @InvokeCimMethodParams) + + if ($Silent) + { + $ProgressPreference = $null + } + } + catch + { + $paramWriteVerbose = @{ + Message = "$_.Exception.Message - Line Number: $_.InvocationInfo.ScriptLineNumber" + ErrorAction = $SC + WarningAction = $SC + } + Write-Verbose @paramWriteVerbose + } + + $GetWinEventParams = @{ + LogName = 'Microsoft-Windows-Dsc/*' + ErrorAction = $SC + WarningAction = $SC + Oldest = $true + } + + # TODO: That is fast, but the code looks bad! + $SuccessResult = (Get-WinEvent @GetWinEventParams | Group-Object -Property { + $_.Properties[0].value + }).Group.LevelDisplayName -notcontains 'Error' + } + + end + { + return $SuccessResult + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Invoke-UpdateAllGalleryModules.ps1 b/Powershell/PowerShell-collection/Misc/Invoke-UpdateAllGalleryModules.ps1 new file mode 100644 index 0000000..2249564 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Invoke-UpdateAllGalleryModules.ps1 @@ -0,0 +1,315 @@ +#requires -Version 3.0 -Modules @{ ModuleName="PowerShellGet"; ModuleVersion="2.0.0" } -RunAsAdministrator + +<# + .SYNOPSIS + Update all PowerShell Modules to the latest PowerShell Gallery version + + .DESCRIPTION + Update all PowerShell Modules to the latest PowerShell Gallery version + + .PARAMETER Silent + Hide the PowerShell Progress Bars + + .EXAMPLE + PS C:\> .\Invoke-UpdateAllGalleryModules.ps1 + Update all PowerShell Modules to the latest PowerShell Gallery version + + .EXAMPLE + PS C:\> .\Invoke-UpdateAllGalleryModules.ps1 -Silent + + Update all PowerShell Modules to the latest PowerShell Gallery version and hide the PowerShell Progress Bars + + .EXAMPLE + PS C:\> .\Invoke-UpdateAllGalleryModules.ps1 -WhatIf + + Dry run the update all PowerShell Modules to the latest PowerShell Gallery version + + .EXAMPLE + PS C:\> .\Invoke-UpdateAllGalleryModules.ps1 -verbose + + Update all PowerShell Modules to the latest PowerShell Gallery version in verbose mode + + .EXAMPLE + PS C:\> .\Invoke-UpdateAllGalleryModules.ps1 -verbose + + Update all PowerShell Modules to the latest PowerShell Gallery version in debug mode + + .NOTES + This is a replacement for some older functions + + .LINK + Invoke-CleanupOldGalleryModuleVersions.ps1 +#> +[CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('NoProgressBars')] + [switch] + $Silent +) + +begin +{ + #region Defaults + $STP = 'Stop' + $CNT = 'Continue' + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region Cleanup + $OriginalProgressPreference = $null + $AllModules = $null + #endregion Cleanup + + #region BoundParameters + if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + { + $VerboseValue = $true + } + else + { + $VerboseValue = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) + { + $DebugValue = $true + } + else + { + $DebugValue = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['WhatIf']).IsPresent) + { + $WhatIfValue = $true + } + else + { + $WhatIfValue = $false + } + #endregion BoundParameters + + if (($PSCmdlet.MyInvocation.BoundParameters['Silent']).IsPresent) + { + # Save the original value + $OriginalProgressPreference = $ProgressPreference + + # Silence is golden... + $ProgressPreference = $SCT + } + + # Get the Module information + $paramGetModule = @{ + ListAvailable = $true + Refresh = $true + ErrorAction = $CNT + WarningAction = $CNT + Verbose = $VerboseValue + Debug = $DebugValue + } + $AllModules = (Get-Module @paramGetModule | Where-Object -FilterScript { + $_.RepositorySourceLocation -like '*powershellgallery*' + } | Select-Object -Property Name, Version, Path) +} + +process +{ + foreach ($SingleModule in $AllModules) + { + # Cleanup + $RepositoryInfo = $null + + <# + The AllowPrerelease is needed here + Find-Module ignored the ErrorAction setting, try/catch will not work + #> + $paramFindModule = @{ + Name = (($SingleModule).Name) + Repository = 'PSGallery' + AllowPrerelease = $true + ErrorAction = $SCT + WarningAction = $CNT + Verbose = $VerboseValue + Debug = $DebugValue + } + $RepositoryInfo = (Find-Module @paramFindModule | Select-Object -Property Name, Version) + + #region CleanVersions + <# + Remove everything from the version string that violates the System.Version class + https://docs.microsoft.com/en-us/dotnet/api/system.version + + e.g. -beta4 or -preview + #> + # Character that we use as a slipt + $SlipPointer = '-' + + # Create the Wildcard to search for + $SplitSearch = ('*' + $SlipPointer + '*') + + if (($SingleModule.Version) -like $SplitSearch) + { + $SingleModule.Version = (($SingleModule.Version).split($SlipPointer)[0]) + } + + if (($RepositoryInfo.Version) -like $SplitSearch) + { + $RepositoryInfo.Version = (($RepositoryInfo.Version).split($SlipPointer)[0]) + } + #endregion CleanVersions + + # Is the online version newer? + if ((($SingleModule).Version) -lt (($RepositoryInfo).Version)) + { + # Cleanup + $ModuleScope = $null + + # try to figure out the scope + if ((($SingleModule).Path) -like ($env:ProgramW6432 + '\*')) + { + $ModuleScope = 'AllUsers' + } + else + { + $ModuleScope = 'CurrentUser' + } + + try + { + Write-Verbose -Message ('Try to update {0}' -f ($SingleModule).Name) + + # Cleanup + $paramUpdateModule = $null + + # Try the Update + $paramUpdateModule = @{ + Name = (($SingleModule).Name) + Scope = $ModuleScope + Force = $true + AcceptLicense = $true + Confirm = $false + Verbose = $VerboseValue + Debug = $DebugValue + WhatIf = $WhatIfValue + ErrorAction = $STP + WarningAction = $CNT + } + $null = (Update-Module @paramUpdateModule) + } + catch + { + try + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Verbose -Message ('Retry to update {0}' -f ($SingleModule).Name) + + # Cleanup + $paramUpdateModule = $null + + # Re-Try the update by allowing prereleases + $paramUpdateModule = @{ + Name = (($SingleModule).Name) + AllowPrerelease = $true + Scope = $ModuleScope + Force = $true + AcceptLicense = $true + Confirm = $false + Verbose = $VerboseValue + Debug = $DebugValue + WhatIf = $WhatIfValue + ErrorAction = $STP + WarningAction = $CNT + } + $null = (Update-Module @paramUpdateModule) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message ('Update of {0} failed' -f ($SingleModule).Name) + } + } + } + else + { + Write-Verbose -Message ('No update for {0} found' -f ($SingleModule).Name) + } + } +} + +end +{ + if ($OriginalProgressPreference) + { + # Restore the old value + $ProgressPreference = $OriginalProgressPreference + } + + # Cleanup + $AllModules = $null + + # Have a great day! +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/LICENSE b/Powershell/PowerShell-collection/Misc/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Misc/Optimize-MicrosoftDefenderExclusions.ps1 b/Powershell/PowerShell-collection/Misc/Optimize-MicrosoftDefenderExclusions.ps1 new file mode 100644 index 0000000..64b8465 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Optimize-MicrosoftDefenderExclusions.ps1 @@ -0,0 +1,311 @@ +<# + .SYNOPSIS + Apply the Defender exclusions based on recommendations by Microsoft + + .DESCRIPTION + Apply the Defender exclusions based on recommendations by Microsoft + + .EXAMPLE + PS C:\> Optimize-MicrosoftDefenderExclusions.ps1 + + .NOTES + Do not just use set-mppreference here, this might remove any existing exclusions. + Might be the right thing to do, but with add-mppreference you append to the list (if exists). + + .LINK + https://support.microsoft.com/en-ie/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/add-mppreference + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference +#> +[CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] +param () + +begin +{ + #region DefaultExclusions + $ExcludePathList = @( + "$env:windir\SoftwareDistribution\DataStore\Datastore.edb", + "$env:windir\SoftwareDistribution\DataStore\Logs\Edb*.jrs", + "$env:windir\SoftwareDistribution\DataStore\Logs\Edb.chk", + "$env:windir\SoftwareDistribution\DataStore\Logs\Tmp.edb", + "$env:windir\Security\Database\*.edb", + "$env:windir\Security\Database\*.sdb", + "$env:windir\Security\Database\*.log", + "$env:windir\Security\Database\*.chk", + "$env:windir\Security\Database\*.jrs", + "$env:windir\Security\Database\*.xml", + "$env:windir\Security\Database\*.csv", + "$env:windir\Security\Database\*.cmtx", + "$env:ProgramData\ntuser.pol", + "$env:windir\System32\GroupPolicy\Machine\Registry.pol", + "$env:windir\System32\GroupPolicy\Machine\Registry.tmp", + "$env:windir\System32\GroupPolicy\User\Registry.pol", + "$env:windir\System32\GroupPolicy\User\Registry.tmp" + ) + #endregion DefaultExclusions + + #region AdExclusions + # Turn off scanning of Active Directory and Active Directory-related files + + # Exclude the Main NTDS database files. + $DSADatabaseFile = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' + $DSADatabaseFilePath = ('Registry::' + $DSADatabaseFile) + if (Test-Path -Path $DSADatabaseFilePath) + { + $DSADatabaseFileValue = (Get-ItemProperty -Path $DSADatabaseFilePath | Select-Object -ExpandProperty 'DSA Database file' -ErrorAction SilentlyContinue) + if ($DSADatabaseFileValue) + { + $ExcludePathList += ($DSADatabaseFileValue) + $ExcludePathList += ($DSADatabaseFileValue).Replace('.dit', '.pat') + } + } + else + { + Write-Verbose -Message 'No NTDS database files to exclude' + } + + # Exclude the Active Directory transaction log files. + $DatabaseLogFiles = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' + $DatabaseLogFilesPath = ('Registry::' + $DatabaseLogFiles) + if (Test-Path -Path $DatabaseLogFilesPath) + { + $DatabaseLogFilesPathValue = (Get-ItemProperty -Path $DatabaseLogFilesPath | Select-Object -ExpandProperty 'Database Log Files Path' -ErrorAction SilentlyContinue) + if ($DatabaseLogFilesPathValue) + { + $ExcludePathList += ($DatabaseLogFilesPathValue + '\EDB*.log') + $ExcludePathList += ($DatabaseLogFilesPathValue + '\Res*.log') + $ExcludePathList += ($DatabaseLogFilesPathValue + '\Edb*.jrs') + $ExcludePathList += ($DatabaseLogFilesPathValue + '\Ntds.pat') + } + } + else + { + Write-Verbose -Message 'No Active Directory transaction log files to exclude' + } + + # Exclude the files in the NTDS Working folder + $DSAWorkingDir = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' + $DSAWorkingDirPath = ('Registry::' + $DSAWorkingDir) + if (Test-Path -Path $DSAWorkingDirPath) + { + $DSAWorkingDirValue = (Get-ItemProperty -Path $DSAWorkingDirPath | Select-Object -ExpandProperty 'DSA Working Directory' -ErrorAction SilentlyContinue) + if ($DSAWorkingDirValue) + { + $ExcludePathList += ($DSAWorkingDirValue + '\Temp.edb') + $ExcludePathList += ($DSAWorkingDirValue + '\Edb.chk') + } + } + else + { + Write-Verbose -Message 'No NTDS Working folder to exclude' + } + #endregion AdExclusions + + #region SysVolExclusions + # Turn off scanning of SYSVOL files + + # Turn off scanning of files in the File Replication Service (FRS) Working folder + $SysVolWorkingDir = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NtFrs\Parameters' + $SysVolWorkingDirPath = ('Registry::' + $SysVolWorkingDir) + if (Test-Path -Path $SysVolWorkingDirPath) + { + $SysVolWorkingDirValue = (Get-ItemProperty -Path $SysVolWorkingDirPath | Select-Object -ExpandProperty 'Working Directory' -ErrorAction SilentlyContinue) + if ($SysVolWorkingDirValue) + { + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\sys\edb.chk') + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\Ntfrs.jdb') + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\log\*.log') + } + } + else + { + Write-Verbose -Message 'No File Replication Service Working folder to exclude' + } + + # Turn off scanning of files in the File Replication Service Database Log files + $SysVolDBLogFileDir = 'HKEY_LOCAL_MACHINE\SYSTEM\Currentcontrolset\Services\Ntfrs\Parameters' + $SysVolDBLogFileDirPath = ('Registry::' + $SysVolDBLogFileDir) + if (Test-Path -Path $SysVolDBLogFileDirPath) + { + $SysVolDBLogFileDirValue = (Get-ItemProperty -Path $SysVolWorkingDirPath | Select-Object -ExpandProperty 'Working Directory' -ErrorAction SilentlyContinue) + if ($SysVolDBLogFileDirValue) + { + $ExcludePathList += ($SysVolDBLogFileDirValue + '\Jet\Log\Edb*.jrs') + } + else + { + if ($SysVolWorkingDirValue) + { + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\Log\Edb*.log') + } + } + } + else + { + Write-Verbose -Message 'No File Replication Service Database Log files to exclude' + } + #endregion SysVolExclusions + + #region DhcpExclusions + # Turn off scanning of DHCP files + $DhcpFiles = 'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\DHCPServer\Parameters' + $DhcpFilesPath = ('Registry::' + $DhcpFiles) + if (Test-Path -Path $DhcpFilesPath) + { + $DhcpDatabasePathValue = (Get-ItemProperty -Path $DhcpFilesPath | Select-Object -ExpandProperty 'DatabasePath' -ErrorAction SilentlyContinue) + if ($DhcpDatabasePathValue) + { + $ExcludePathList += ($DhcpDatabasePathValue + '\*.mdb') + $ExcludePathList += ($DhcpDatabasePathValue + '\*.pat') + $ExcludePathList += ($DhcpDatabasePathValue + '\*.chk') + $ExcludePathList += ($DhcpDatabasePathValue + '\*.edb') + } + + $DhcpLogFilePathValue = (Get-ItemProperty -Path $DhcpFilesPath | Select-Object -ExpandProperty 'DhcpLogFilePath' -ErrorAction SilentlyContinue) + if (($DhcpLogFilePathValue) -and ($DhcpLogFilePathValue -ne $DhcpDatabasePathValue)) + { + $ExcludePathList += ($DhcpLogFilePathValue + '\*.log') + } + else + { + $ExcludePathList += ($DhcpDatabasePathValue + '\*.log') + } + + $DhcpBackupDatabasePathValue = (Get-ItemProperty -Path $DhcpFilesPath | Select-Object -ExpandProperty 'BackupDatabasePath' -ErrorAction SilentlyContinue) + if ($DhcpBackupDatabasePathValue) + { + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.mdb') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.pat') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.chk') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.edb') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.log') + } + } + else + { + Write-Verbose -Message 'No DHCP Server Directory found' + } + #endregion DhcpExclusions + + #region DnsExclusions + $DnsServerDir = "$env:windir\System32\dns" + if (Test-Path -Path $DnsServerDir -ErrorAction SilentlyContinue) + { + $ExcludePathList += ($DnsServerDir + '\*.log') + $ExcludePathList += ($DnsServerDir + '\*.dns') + $ExcludePathList += ($DnsServerDir + '\BOOT') + + $DnsBackupServerDir = ($DnsServerDir + '\backup') + if (Test-Path -Path $DnsBackupServerDir -ErrorAction SilentlyContinue) + { + $ExcludePathList += ($DnsBackupServerDir + '\*.log') + $ExcludePathList += ($DnsBackupServerDir + '\*.dns') + $ExcludePathList += ($DnsBackupServerDir + '\BOOT') + } + } + else + { + Write-Verbose -Message 'No DNS Server Directory found' + } + #endregion DnsExclusions + + #region WinsExclusions + $WinsServerDir = "$env:windir\System32\Wins" + if (Test-Path -Path $WinsServerDir -ErrorAction SilentlyContinue) + { + Write-Warning -Message 'WINS is still installed on this system!' -WarningAction Continue + + $ExcludePathList += ($WinsServerDir + '\*.chk') + $ExcludePathList += ($WinsServerDir + '\*.log') + $ExcludePathList += ($WinsServerDir + '\*.mdb') + } + else + { + Write-Verbose -Message 'No WINS Server Directory found' + } + #endregion WinsExclusions +} + +process +{ + if ($pscmdlet.ShouldProcess($ExcludePathList, 'Exclude from Microsoft Defender Scanning')) + { + # Loop over the list we created + foreach ($ExcludePath in $ExcludePathList) + { + try + { + # Splat the parameters for Add-MpPreference + $SplatAddMpPreference = @{ + ExclusionPath = $ExcludePath + Force = $true + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (Add-MpPreference @SplatAddMpPreference) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Error Stack + $info | Out-String | Write-Verbose + + # Just display the info on continue with the rest of the list + Write-Warning -Message ($info.Exception) -ErrorAction Continue -WarningAction Continue + + # Cleanup + $info = $null + $e = $null + #endregion ErrorHandler + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Optimize-MicrosoftDefenderExclusionsForMicrosoftTeams.ps1 b/Powershell/PowerShell-collection/Misc/Optimize-MicrosoftDefenderExclusionsForMicrosoftTeams.ps1 new file mode 100644 index 0000000..56bafce --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Optimize-MicrosoftDefenderExclusionsForMicrosoftTeams.ps1 @@ -0,0 +1,133 @@ +<# + .SYNOPSIS + Add Defender Antivirus Exclusions for the Teams Desktop Client for a given User + + .DESCRIPTION + Add Defender Antivirus Exclusions for the Teams Desktop Client for a given User + + .PARAMETER Username + Username to apply the exclusion to. + Please Note: The user 'john.doe' in the domain 'CONTOSO' will have the username 'john.doe.CONTOSO'. This is the case to have the connect Directory (Windows naming convention). + + .EXAMPLE + PS C:\> .\Optimize-MicrosoftDefenderExclusionsForMicrosoftTeams.ps1 -Username 'john.doe.CONTOSO' + + Apply the Defender Antivirus Exclusions for the user 'john.doe' in the domain 'CONTOSO'. + In this case, the $env:USERPROFILE Directory will be 'C:\Users\john.doe.CONTOSO' + + .NOTES + This is a more flexible version of Add-DefenderExclusionsForMicrosoftteams.ps1 that brings username as a parameter. + I crerated this because my user does NOT have Admin permissions on my local windows boxes and with this version, I can apply it with my admin account, biut for my regular user (or any other user on the local system) + + Do not just use set-mppreference here, this might remove any existing exclusions. + Might be the right thing to do, but with add-mppreference you append to the list (if exists). + + .LINK + https://gist.github.com/jhochwald/866ce1c5ac894397979f38fa9720b8ff + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/add-mppreference + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param +( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Username to apply the exclusion to.')] + [ValidateNotNullOrEmpty()] + [Alias('User', 'Name')] + [string] + $Username +) + +begin +{ + $ExcludePathList = @( + ('C:\Users\' + $Username + '\Microsoft\Teams\Update.exe'), + ('C:\Users\' + $Username + '\Microsoft\Teams\current\Teams.exe'), + ('C:\Users\' + $Username + '\Microsoft\Teams\'), + ('C:\Users\' + $Username + '\Microsoft\Teams\') + ) +} + +process +{ + # Loop over the list we created + foreach ($ExcludePath in $ExcludePathList) + { + try + { + # Splat the parameters for Add-MpPreference + $SplatAddMpPreference = @{ + ExclusionPath = $ExcludePath + Force = $true + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (Add-MpPreference @SplatAddMpPreference) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Error Stack + $info | Out-String | Write-Verbose + + # Just display the info on continue with the rest of the list + Write-Warning -Message ($info.Exception) -ErrorAction Continue -WarningAction Continue + + # Cleanup + $info = $null + $e = $null + #endregion ErrorHandler + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Out-ZipArchive.ps1 b/Powershell/PowerShell-collection/Misc/Out-ZipArchive.ps1 new file mode 100644 index 0000000..81f6697 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Out-ZipArchive.ps1 @@ -0,0 +1,229 @@ +function Out-ZipArchive +{ + <# + .SYNOPSIS + Creates a ZIP Archive + + .DESCRIPTION + Creates a ZIP Archive with all given Files (and subdirectories) + + .PARAMETER Path + Input Path + + .PARAMETER ArchiveName + Name of the archive to create. + + .PARAMETER force + Enforce overwrite? + + .PARAMETER fallback + Use Microsoft .NET Framework API instead of Compress-Archive (Bundled with PowerShell 5.0, or later) + + .EXAMPLE + PS C:\> Out-ZipArchive -Path 'Value1' -ArchiveName 'Value2' + + Creates a ZIP Archive with all given Files (and subdirectories) + + .EXAMPLE + PS C:\> Out-ZipArchive -Path 'Value1' -ArchiveName 'Value2' -fallback + + Creates a ZIP Archive with all given Files (and subdirectories) - Use .NET Framework API instead of Compress-Archive internal + + .NOTES + We now use Compress-Archive by default. It is build upon the Microsoft .NET Framework API System.IO.Compression.ZipArchive and has the same limitation. + + .LINK + Compress-Archive + + .LINK + https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.archive/compress-archive + #> + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 0, + HelpMessage = 'Input Path')] + [ValidateNotNullOrEmpty()] + [Alias('Directory')] + [string] + $Path, + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 1, + HelpMessage = 'Name of the archive to create')] + [ValidateNotNullOrEmpty()] + [Alias('FileName')] + [string] + $ArchiveName, + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 2)] + [Alias('overwrite')] + [switch] + $force, + [Parameter(ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 3)] + [Alias('dotnet')] + [switch] + $fallback = $false + ) + + begin + { + $null = (Add-Type -AssemblyName System.IO.Compression.FileSystem) + + $compressionLevel = [IO.Compression.CompressionLevel]::Optimal + + Write-Verbose -Message "Compression level for $ArchiveName is $compressionLevel" + + # Safe ProgressPreference and Setup SilentlyContinue for the function + $ExistingProgressPreference = ($ProgressPreference) + $ProgressPreference = 'SilentlyContinue' + } + + process + { + + if (-not $ArchiveName.EndsWith('.zip')) + { + Write-Verbose -Message "Bad filename detected $ArchiveName" + + $ArchiveName += '.zip' + + Write-Verbose -Message "Corrected filename is $ArchiveName" + } + + if ($force) + { + if (Test-Path -Path $ArchiveName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue) + { + Write-Verbose -Message "Overwrite old archive $ArchiveName" + + try + { + $paramRemoveItem = @{ + Path = $ArchiveName + Force = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (Remove-Item @paramRemoveItem) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -TargetObject ($info.Target) -ErrorAction Stop + break + } + } + } + + try + { + Write-Verbose -Message "Try to create archive $ArchiveName" + + if ($fallback) + { + Write-Verbose -Message 'Run in fallback mode and using System.IO.Compression.ZipArchive instead of Compress-Archive' + $zip = ([IO.Compression.ZipFile]::CreateFromDirectory($Path, $ArchiveName, $compressionLevel, $false)) + # And always make sure to close the locks on that file + $zip.Dispose() + } + else + { + $paramCompressArchive = @{ + Path = $Path + CompressionLevel = $compressionLevel + DestinationPath = $ArchiveName + Force = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $null = (Compress-Archive @paramCompressArchive) + } + + Write-Verbose -Message "Archive $ArchiveName was created" + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -TargetObject ($info.Target) -ErrorAction Stop + break + } + } + + end + { + # Restore ProgressPreference + $ProgressPreference = $ExistingProgressPreference + + Write-Verbose -Message 'Out-ZipArchive done' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Publish-BitbucketDownload.ps1 b/Powershell/PowerShell-collection/Misc/Publish-BitbucketDownload.ps1 new file mode 100644 index 0000000..2a52091 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Publish-BitbucketDownload.ps1 @@ -0,0 +1,245 @@ +function Publish-BitbucketDownload +{ + <# + .SYNOPSIS + Upload given file to BitBucket cloud service downloads section. + + .DESCRIPTION + Upload given file to BitBucket cloud service downloads section. + I use this to upload build artifacts to the BitBucket Download section. + + The code might not be perfect, and we still use the AUTH Header instead of OAuth yet, + but I needed a quick and dirty solution to get things going. + + I might change a few things soon, but for now; this function is doing what it should. + + .PARAMETER username + BitBucket cloud username, as plain text + + .PARAMETER password + BitBucket cloud password, as plain text + + .PARAMETER FilePath + File to upload, full path needed + + .PARAMETER team + BitBucket cloud team aka username (Might not be the login username!!!) + + .PARAMETER Project + BitBucket cloud project name + + .EXAMPLE + PS ~> Publish-BitbucketDownload -username 'MyUsername' -password 'MySectretPassword' -FilePath 'Y:\dev\release\myproject-current.zip' -team 'dummyTeam' -Project 'myproject' + + # Upload the artifact 'Y:\dev\release\myproject-current.zip' to the Download sections of the 'myproject' project of the 'dummyTeam', It uses User name and password (Both in plain ASC) to authenticate. However, both are converted to base64 to prevent any clear text header transfers. + + .EXAMPLE + PS ~> Publish-BitbucketDownload -username 'MyUsername' -password 'MySectretPassword' -FilePath 'Y:\dev\release\myproject.nuget' -team 'dummyTeam' -Project 'myproject' + + # Upload the artifact 'Y:\dev\release\myproject.nuget' to the Download sections of the 'myproject' project of the 'dummyTeam', It uses Username and password (Both in plain ASC) to authenticate. However, both are converted to base64 to prevent any clear text header transfers. + + .NOTES + I created this because I did not have CURL installed on my build system. + + With Curl this is an absolute no brainer: + curl -X POST "https://MyUsername:MySectretPassword@api.bitbucket.org/2.0/repositories/dummyTeam/myproject/downloads" --form files=@"/home/dev/release\myproject-current.zip" + + INFO: Max. CPU: 16 % Max. Memory: 28.48 MB + + TODO: Convert the request to use OAuth ASAP + #> + [CmdletBinding()] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + HelpMessage = 'BitBucket cloud username, as plain text')] + [ValidateNotNullOrEmpty()] + [Alias('user')] + [string] + $username, + [Parameter(Mandatory, + ValueFromPipeline, + HelpMessage = 'BitBucket cloud password, as plain text')] + [ValidateNotNullOrEmpty()] + [Alias('pass')] + [string] + $password, + [Parameter(Mandatory, + ValueFromPipeline, + HelpMessage = 'File to upload, full path needed')] + [ValidateNotNullOrEmpty()] + [string] + $FilePath, + [Parameter(Mandatory, + ValueFromPipeline, + HelpMessage = 'BitBucket cloud team name')] + [ValidateNotNullOrEmpty()] + [string] + $team, + [Parameter(Mandatory, + ValueFromPipeline, + HelpMessage = 'BitBucket cloud project name')] + [ValidateNotNullOrEmpty()] + [Alias('ProjectName')] + [string] + $Project + ) + + process + { + # Build the URI for our request + $URI = 'https://api.bitbucket.org/2.0/repositories/' + $team + '/' + $Project + '/downloads' + + # Create our authentication header + # TODO: Migrate to OAUTH + $pair = ($username + ':' + $password) + $encodedCreds = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair)) + $basicAuthValue = ('Basic {0}' -f $encodedCreds) + $Headers = @{ + Authorization = $basicAuthValue + } + + # Cleanup the plain text stuff + $pair = $null + $encodedCreds = $null + + # The boundary is essential - Trust me, very essential + $boundary = [Guid]::NewGuid().ToString() + + <# + This is the crappy part: Build a body for a multipart request with PowerShell + + This is something that should be changed in PowerShell ASAP (I mean it is really crappy and really bad). + + It is an absolute no brainer with Curl. + #> + $bodyStart = @" +--$boundary +Content-Disposition: form-data; name="token" + +--$boundary +Content-Disposition: form-data; name="files"; filename="$(Split-Path -Leaf -Path $FilePath)" +Content-Type: application/octet-stream + + +"@ + + # Generate the end of the request body to finish it. + $bodyEnd = @" + +--$boundary-- +"@ + + # Now we create a temp file (Another crappy/bad thing) + $requestInFile = (Join-Path -Path $env:TEMP -ChildPath ([IO.Path]::GetRandomFileName())) + + try + { + # Create a new object for the brand new temporary file + $fileStream = (New-Object -TypeName 'System.IO.FileStream' -ArgumentList ($requestInFile, [IO.FileMode]'Create', [IO.FileAccess]'Write')) + + try + { + # The Body start + $bytes = [Text.Encoding]::UTF8.GetBytes($bodyStart) + $fileStream.Write($bytes, 0, $bytes.Length) + + # The original File + $bytes = [IO.File]::ReadAllBytes($FilePath) + $fileStream.Write($bytes, 0, $bytes.Length) + + # Append the end of the body part + $bytes = [Text.Encoding]::UTF8.GetBytes($bodyEnd) + $fileStream.Write($bytes, 0, $bytes.Length) + } + finally + { + # End the Stream to close the file + $fileStream.Close() + + # Cleanup + $fileStream = $null + + # PowerShell garbage collector + [GC]::Collect() + } + + # Make it multipart, this is the magic part... + $contentType = 'multipart/form-data; boundary={0}' -f $boundary + + <# + The request itself is simple and easy, also works fine with Invoke-WebRequest instead of Invoke-RestMethod + + I use Microsoft.PowerShell.Utility\Invoke-RestMethod to make sure the build in (Windows PowerShell native) function is used. + If PowerShell Core is installed or any Module provides a tweaked version... Just in case! + #> + try + { + $null = (Microsoft.PowerShell.Utility\Invoke-RestMethod -Uri $URI -Method Post -InFile $requestInFile -ContentType $contentType -Headers $Headers -ErrorAction Stop -WarningAction SilentlyContinue) + } + catch + { + # Remove the temp file + $null = (Remove-Item -Path $requestInFile -Force -Confirm:$false) + + # Cleanup + $contentType = $null + + # PowerShell garbage collector + [GC]::Collect() + + # For the Build logs (will not break the build) + Write-Warning -Message 'StatusCode:' $_.Exception.Response.StatusCode.value__ + Write-Warning -Message 'StatusDescription:' $_.Exception.Response.StatusDescription + + # Saved in the verbose logs for this build + Write-Verbose -Message $_ + + # Inform the build and terminate (Will break the build) + Write-Error -Message 'We were unable to upload your file to the BitBucket downloads section, please check the build logs for further information.' -ErrorAction Stop + } + } + finally + { + # Remove the temp file + $null = (Remove-Item -Path $requestInFile -Force -Confirm:$false) + + # Cleanup + $contentType = $null + + # PowerShell garbage collector + [GC]::Collect() + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Remove-FileEndingBlankLines.ps1 b/Powershell/PowerShell-collection/Misc/Remove-FileEndingBlankLines.ps1 new file mode 100644 index 0000000..1466c31 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Remove-FileEndingBlankLines.ps1 @@ -0,0 +1,211 @@ +function Remove-FileEndingBlankLines +{ + <# + .SYNOPSIS + Strip white space/blank lines from end of file or path + + .DESCRIPTION + Strip white space/blank lines from end of file or path + + .PARAMETER Path + Single File or Path you want to unclutter. (Mandatory) + + .PARAMETER Recurse + Recurse through all subdirectories of the path provided. The default is not work recursively (Optional) + + .PARAMETER noNewLine + No new (blank) line at the end of a file. + + .PARAMETER SafeFilesOnly + Only safe files were processed. This is the default! This will prevent any issues with Binary Files or any other non safe to process files. If you like to process all files (can be dangerous) just negate this by using -SafeFilesOnly:$false + + .EXAMPLE + PS C:\> Remove-FileEndingBlankLines -Path 'C:\Temp\Export-DistributionGroup2Cloud.ps1' + + Strip white space/blank lines from end of 'C:\Temp\Export-DistributionGroup2Cloud.ps1' + + .EXAMPLE + PS C:\> Remove-FileEndingBlankLines -Path 'C:\Temp\Export-DistributionGroup2Cloud.ps1' + + Strip white space/blank lines from end of 'C:\Temp\Export-DistributionGroup2Cloud.ps1' without ending a final blank line at the end. + NOTE: Set-Content adds a final blank line by default. this switch prevents this! + + .EXAMPLE + PS C:\> Remove-FileEndingBlankLines -Path 'C:\Temp' -Recurse + + Strip white space/blank lines from end of files found in 'C:\Temp' and below (recursively). + + .EXAMPLE + PS C:\> Remove-FileEndingBlankLines -Path 'C:\Temp' -Recurse -SafeFilesOnly:$false + + Strip white space/blank lines from end of all files found in 'C:\Temp' and below (recursively). + This might be risky and/or even dangerous! If you process any binary files, they might be corrupt afterwards. + + .NOTES + I created this helper function to unclutter the file ends and white space/blank lines from files during my build process. + + I prefer the way that Set-Content handles it: Add a single blank line at the end of each file. This is use to the fact, that I concatenate several files during a build process. + + I also added a switch (noNewLine) to prevent this. + + By default only PowerShell and Markdown Files are processed by this function + + .LINK + Set-Content + + .LINK + Get-Content + #> + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Single File or Path you want to unclutter.')] + [ValidateNotNullOrEmpty()] + [Alias('FilePath')] + [string] + $Path, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [switch] + $Recurse = $false, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 3)] + [switch] + $noNewLine = $false, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 4)] + [switch] + $SafeFilesOnly = $true + ) + + begin + { + $paramGetChildItem = @{ + Path = $Path + File = $true + } + + if ($SafeFilesOnly) + { + Write-Verbose -Message 'Only safe files are processed' + $paramGetChildItem.Include = '*.psm1', '*.ps1', '*.psd1', '*.ps1xml', '*.md' + } + else + { + Write-Verbose -Message 'All are processed - Might be a bad idea!!!' + } + + if ($Recurse) + { + Write-Verbose -Message 'Read the info recursively' + $paramGetChildItem.Recurse = $true + } + else + { + Write-Verbose -Message 'Read the info' + } + } + + process + { + # Make sure only files are processed and get the minimal info + (Get-ChildItem @paramGetChildItem | Where-Object -FilterScript { + -not $_.PSIsContainer + } | Select-Object -ExpandProperty FullName) | ForEach-Object -Process { + Write-Verbose -Message ('Try to unclutter {0}' -f $_) + + $UnclutteredText = (((Get-Content -Path $_ -Raw).TrimEnd()).ToString()) + + try + { + if ($noNewLine) + { + Write-Verbose -Message ('Try to unclutter {0} (no final new line)' -f $_) + + $null = ([io.file]::WriteAllText($_.FullName, $UnclutteredText)) + } + else + { + Write-Verbose -Message ('Try to unclutter {0}' -f $_) + + $paramSetContent = @{ + Path = $_ + Value = $UnclutteredText + Force = $true + Confirm = $false + Encoding = 'UTF8' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (Set-Content @paramSetContent) + } + + Write-Verbose -Message ('Uncluttered {0}' -f $_) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -TargetObject ($info.Target) -ErrorAction Stop + break + } + } + } + + end + { + Write-Verbose -Message 'Clear-FileEnding Done' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Remove-Signature.ps1 b/Powershell/PowerShell-collection/Misc/Remove-Signature.ps1 new file mode 100644 index 0000000..9e222fe --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Remove-Signature.ps1 @@ -0,0 +1,188 @@ +function Remove-Signature +{ + <# + .SYNOPSIS + Finds all signed PowerShell files removes any digital signatures attached to them. + + .DESCRIPTION + Finds all signed PowerShell files removes any digital signatures attached to them. + Supported Filetypes are: psm1, ps1, psd1, and ps1xml - All other Files are ignored! + + .PARAMETER Path + Single File or Path you want to parse for digital signatures. (Mandatory) + + .PARAMETER Recurse + Recurse through all subdirectories of the path provided. The default is not work recursively (Optional) + + .EXAMPLE + PS C:\> Remove-Signature -Path 'C:\Temp\Export-DistributionGroup2Cloud.ps1' + + Removes all digital signatures from 'C:\Temp\Export-DistributionGroup2Cloud.ps1' + + .EXAMPLE + PS C:\> Remove-Signature -Path 'C:\Temp' -Recurse + + Removes all digital signatures from psm1, ps1, psd1, and ps1xml files found in 'C:\Temp' and below (recursively). + + .NOTES + Based on the ideas and work of the original Authors: Adrian Rodriguez and Zachary Loeber + + .LINK + http://www.the-little-things.net + + .LINK + https://psrdrgz.github.io/RemoveAuthenticodeSignature/ + #> + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Single File or Path you want to parse for digital signatures.')] + [ValidateNotNullOrEmpty()] + [Alias('FilePath')] + [string] + $Path, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [switch] + $Recurse = $false + ) + + begin + { + $paramGetChildItem = @{ + Path = $Path + File = $true + Include = '*.psm1', '*.ps1', '*.psd1', '*.ps1xml' + } + + if ($Recurse) + { + Write-Verbose -Message 'Work recursively' + $paramGetChildItem.Recurse = $true + } + } + + process + { + + $FilesToProcess = (Get-ChildItem @paramGetChildItem) + + $FilesToProcess | ForEach-Object -Process { + $SignatureStatus = (Get-AuthenticodeSignature -FilePath $_).Status + $ScriptFileFullName = $_.FullName + + if ($SignatureStatus -ne 'NotSigned') + { + try + { + $paramGetContent = @{ + Path = $ScriptFileFullName + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $Content = (Get-Content @paramGetContent) + + $paramNewObject = @{ + TypeName = 'System.Text.StringBuilder' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $StringBuilder = (New-Object @paramNewObject) + + foreach ($Line in $Content) + { + if ($Line -match '^# SIG # Begin signature block|^') + { + break + } + else + { + $null = $StringBuilder.AppendLine($Line) + } + } + if ($pscmdlet.ShouldProcess("$ScriptFileFullName")) + { + $paramSetContent = @{ + Path = $ScriptFileFullName + Value = $StringBuilder.ToString() + Force = $true + Confirm = $false + Encoding = 'UTF8' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (Set-Content @paramSetContent) + + Write-Verbose -Message ('Removed signature from {0}' -f $ScriptFileFullName) + } + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -TargetObject ($info.Target) -ErrorAction Stop + break + } + } + else + { + Write-Verbose -Message ('No signature found in {0}' -f $ScriptFileFullName) + } + } + } + + end + { + Write-Verbose -Message 'Remove-Signature Done' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Resolve-DNSHost.ps1 b/Powershell/PowerShell-collection/Misc/Resolve-DNSHost.ps1 new file mode 100644 index 0000000..7b5447f --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Resolve-DNSHost.ps1 @@ -0,0 +1,118 @@ +function Resolve-DNSHost +{ + <# + .SYNOPSIS + Resolve DNS hostname to IP and reverse + + .DESCRIPTION + This function resolves DNS hostname to IP and the other way around (reverse) + + .PARAMETER HostEntry + Hostname (Single, or multiple) to test. + + .EXAMPLE + PS C:\> Resolve-DNSHost -HostEntry www.hochwald.net + + HostName IPAddress + -------- --------- + www.hochwald.net {104.28.0.64, 104.28.1.64, 2606:4700:30::681c:140, 2606:4700:30::681c:40} + + This function resolves DNS hostname to IP and the other way around (reverse) + + .EXAMPLE + PS C:\> Resolve-DNSHost -HostEntry 'www.hochwald.net','autodiscover.hochwald.net' + + HostName IPAddress + -------- --------- + www.hochwald.net {104.28.0.64, 104.28.1.64, 2606:4700:30::681c:140, 2606:4700:30::681c:40} + autodiscover.hochwald.net {40.101.88.8, 40.101.88.184, 52.97.151.104, 40.101.60.24...} + + This function resolves DNS hostname to IP and the other way around (reverse) + + .OUTPUTS + psobject + + .NOTES + Refactored of Resolve-Host.Ps1 by @PrateekKumarSingh + + .LINK + Original: + https://gist.github.com/PrateekKumarSingh/586f2d3d43f7e8cb07ce + + .LINK + Dns Class (system.net.dns): + https://docs.microsoft.com/de-de/dotnet/api/system.net.dns + + .INPUTS + String + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Hostname (Single, or multiple) to test.')] + [ValidateNotNullOrEmpty()] + [String[]] + $HostEntry + ) + + begin + { + # Cleanup + $Obj = @() + $Object = @() + } + + process + { + $HostEntry | ForEach-Object -Process { + $Obj += New-Object -TypeName psobject -Property @{ + HostName = $_ + IPAddress = $([Net.Dns]::gethostentry($_).AddressList.IPAddressToString) + } + } + + # Append + $Object = ($Obj | Select-Object -Property Hostname, IPAddress) + } + + end + { + # Dump to the console + $Object + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Set-AllowPingAndRemoteDesktop.ps1 b/Powershell/PowerShell-collection/Misc/Set-AllowPingAndRemoteDesktop.ps1 new file mode 100644 index 0000000..9b2230b --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Set-AllowPingAndRemoteDesktop.ps1 @@ -0,0 +1,133 @@ +#requires -Version 3.0 -Modules NetSecurity -RunAsAdministrator + +<# + .SYNOPSIS + Enable inbound ICMP (Ping) and Remote Desktop (RDP) + + .DESCRIPTION + Enable inbound ICMP (Ping) and Remote Desktop (RDP). + Ping will be enabled for IPv4 and IPv6. + + .PARAMETER RDPGroup + Enable the complete RDP Groups in the Windows Firewall? + This will enable more then just the basic requirements, use with care!!! + + .EXAMPLE + PS C:\> .\Set-AllowPingAndRemoteDesktop.ps1 + + Enable inbound ICMP (Ping) and Remote Desktop (RDP) + + .EXAMPLE + PS C:\> .\Set-AllowPingAndRemoteDesktop.ps1 -verbose + + Enable inbound ICMP (Ping) and Remote Desktop (RDP) - verbose run + + .EXAMPLE + PS C:\> .\Set-AllowPingAndRemoteDesktop.ps1 -WhatIf + + Enable inbound ICMP (Ping) and Remote Desktop (RDP) - Dry run + + .NOTES + Helper script I use to bootstrap servers + Run this elevated!!! +#> +[CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline)] + [switch] + $RDPGroup +) + +begin +{ + # Splat the Set-ItemProperty parameters + $paramSetItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Control\Terminal Server' + Name = 'fDenyTSConnections' + Value = 0 + ErrorAction = 'Continue' + } + + # Splat the Enable-NetFirewallRule parameters + $paramEnableNetFirewallRule = @{ + Confirm = $false + ErrorAction = 'Continue' + } +} + +process +{ + # Support WhatIf (SupportsShouldProcess) + if ($pscmdlet.ShouldProcess('Registry Terminal Server', 'Modify')) + { + # Tweak the Registry for Remote Desktop connections + $null = (Set-ItemProperty @paramSetItemProperty) + } + + # We avoid using $RDPGroup.IsPresent + if ($PSBoundParameters.ContainsKey('RDPGroup')) + { + if ($pscmdlet.ShouldProcess('Firewall Group for Remote Desktop', 'Enable')) + { + # Allow Remote Desktop (The Group) + $null = (Get-NetFirewallRule -DisplayGroup 'Remote Desktop' -ErrorAction SilentlyContinue | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule) + } + } + else + { + if ($pscmdlet.ShouldProcess('Firewall Rules for Remote Desktop', 'Enable')) + { + # Alternative Approach: Enable the minimum, not the Group + Get-NetFirewallRule -Name 'RemoteDesktop-UserMode-In-TCP' -ErrorAction SilentlyContinue | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule + + Get-NetFirewallRule -DisplayName 'Remote Desktop - User Mode (TCP-In)' -ErrorAction SilentlyContinue | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule + } + } + + if ($pscmdlet.ShouldProcess('Ping', 'Enable')) + { + # Allow Ping for IPv4 and IPv6 + # NOTE: The wildcard (ICMPv?) will select both. Replace it with 4 or 6 to use just one of them + Get-NetFirewallRule -DisplayName 'File and Printer Sharing (Echo Request - ICMPv?-In)' -ErrorAction SilentlyContinue | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Set-ChromeDefaultPreferences.ps1 b/Powershell/PowerShell-collection/Misc/Set-ChromeDefaultPreferences.ps1 new file mode 100644 index 0000000..8117ecf --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Set-ChromeDefaultPreferences.ps1 @@ -0,0 +1,520 @@ +<# + .SYNOPSIS + Change the Google Chrome config to some defaults + + .DESCRIPTION + Change the Google Chrome config to some defaults. + Chromium or any other Chromium based browsers are not yet supported. + + .PARAMETER Profile + Name of the Google Chrome Profile. + The default is Default + + .EXAMPLE + PS C:\> .\Set-ChromeDefaultPreferences.ps1 + + Change the Google Chrome config to some defaults. + We use the default profile (Default) + + .EXAMPLE + PS C:\> .\Set-ChromeDefaultPreferences.ps1 -Profile 'Work' + + Change the Google Chrome config to some defaults + We use the profile Work and not the default one + + .NOTES + Chromium or any other Chromium based browsers are not yet supported. + + I created this to tweak the existing Google Chrome configuration. + + This is open-source software, if you find an issue try to fix it yourself. + There is no support and/or warranty in any kind + + .LINK + http://www.enatec.io + + .LINK + Get-Process + + .LINK + Stop-Process + + .LINK + ConvertFrom-Json + + .LINK + Test-Path + + .LINK + Get-Content + + .LINK + Where-Object + + .LINK + Add-Member + + .LINK + ConvertTo-Json + + .LINK + Set-Content +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [AllowNull()] + [Alias('ChromeProfile', 'ChromeProfileName', 'ProfileName')] + [string] + $Profile = 'Default' +) + +begin +{ + #region Cleanup + $NewConfig = $null + $ChromePreferencesValues = $null + $DefaultConfigValues = $null + $Property = $null + #endregion Cleanup + + #region Defaults + if ($Profile) + { + # We have an command line parameter, so we use this + $ChromeProfile = $Profile + } + else + { + # We do NOT have an command line parameter, so we add a default + $ChromeProfile = 'Default' + } + + $Encoding = 'UTF8' + $STP = 'Stop' + + # Create the new object + $NewConfig = @{ + } + #endregion Defaults + + #region PSEdition + if ($PSVersionTable.PSEdition -eq 'Desktop') + { + # Desktop Edition - Windows + $BaseChromeProfilePath = "$env:LOCALAPPDATA\Google\Chrome\User Data\" + + #region KillChrome + #region Splat + $paramGetProcess = @{ + Name = 'chrome' + ErrorAction = 'SilentlyContinue' + } + + $paramStopProcess = @{ + Force = $true + ErrorAction = 'SilentlyContinue' + } + #endregion Splat + + # Kill Chrome + $null = (Get-Process @paramGetProcess | Stop-Process @paramStopProcess) + #endregion KillChrome + } + elseif ($PSVersionTable.PSEdition -eq 'Core') + { + #region PowerShellCoreHandling + if ($IsLinux -eq $true) + { + # Core Edition - Linux/Unix + #region Splat + $paramWriteWarning = @{ + Message = 'PowerShell Core on Linux/Unix is not yet tested or supported' + } + #endregion Splat + + Write-Warning @paramWriteWarning + + #region Splat + $paramWriteError = @{ + Message = 'Sorry, Linux is not yet supüported' + Category = 'OperationStopped' + ErrorAction = $STP + } + #endregion Splat + + Write-Error @paramWriteError + } + elseif ($IsMacOS -eq $true) + { + # Core Edition - macOS or Mac OSX + $BaseChromeProfilePath = "$env:HOME/Library/Application Support/Google/Chrome/" + + #region KillChrome + #region Splat + $paramGetProcess = @{ + Name = 'Google Chrome*' + ErrorAction = 'SilentlyContinue' + } + + $paramStopProcess = @{ + Force = $true + ErrorAction = 'SilentlyContinue' + } + #endregion Splat + + # Kill Chrome + $null = (Get-Process @paramGetProcess | Stop-Process @paramStopProcess) + #endregion KillChrome + } + elseif ($IsWindows -eq $true) + { + # Core Edition - Windows + $BaseChromeProfilePath = "$env:LOCALAPPDATA\Google\Chrome\User Data\" + } + else + { + #region Splat + $paramWriteError = @{ + Message = 'Unknown PowerShell Core installation' + Category = 'NotEnabled' + ErrorAction = $STP + } + #endregion Splat + + Write-Error @paramWriteError + } + #endregion PowerShellCoreHandling + } + else + { + #region Splat + $paramWriteError = @{ + Message = 'Unknown PowerShell Edition' + Category = 'InvalidOperation' + ErrorAction = $STP + } + #endregion Splat + + Write-Error @paramWriteError + } + #endregion PSEdition + + #region DefaultConfig + #region DefaultConfigJson + <# + Could be an external file, but embedded is easier to handle. + Looks crappy, but it works fine! + #> + $DefaultConfigJson = '{ + "credentials_enable_autosignin": false, + "credentials_enable_service": false, + "enable_do_not_track": true, + "default_apps": "noinstall", + "alternate_error_pages": { + "enabled": false + }, + "distribution": { + "import_bookmarks": false, + "make_chrome_default": false, + "make_chrome_default_for_user": false, + "verbose_logging": true, + "skip_first_run_ui": true, + "create_all_shortcuts": true, + "suppress_first_run_default_browser_prompt": true + }, + "autofill": { + "enabled": false, + "credit_card_enabled": false, + "profile_enabled": false, + "use_mac_address_book": false + }, + "bookmark_bar": { + "show_apps_shortcut": false, + "show_on_all_tabs": true + }, + "browser": { + "show_home_button": true, + "has_seen_welcome_page": true, + "check_default_browser": false + }, + "custom_handlers": { + "enabled": false, + "ignored_protocol_handlers": [], + "registered_protocol_handlers": [] + }, + "intl": { + "accept_languages": "en-US,en,de-DE,de" + }, + "net": { + "network_prediction_options": 2 + }, + "profile": { + "block_third_party_cookies": false, + "password_manager_enabled": false, + "default_content_setting_values": { + "geolocation": 1, + "media_stream_camera": 2, + "media_stream_mic": 2, + "notifications": 2, + "plugins": 2, + "popups": 2, + "ppapi_broker": 2, + "midi_sysex": 2, + "payment_handler": 2 + } + }, + "safebrowsing": { + "enabled": true, + "scout_reporting_enabled": false + }, + "search": { + "suggest_enabled": false + }, + "signin": { + "allowed": false, + "allowed_on_next_startup": false + }, + "spellcheck": { + "use_spelling_service": false + }, + "tranSplate": { + "enabled": false + }, + "tranSplate_blocked_languages": [ + "en", + "de" + ], + "dns_prefetching": { + "enabled": false + }, + "payments": { + "can_make_payment_enabled": false + }, + "webkit": { + "webprefs": { + "tabs_to_links": true + } + } + }' + #endregion DefaultConfigJson + + #region Splat + $paramConvertFromJson = @{ + InputObject = $DefaultConfigJson + ErrorAction = $STP + } + #endregion Splat + + # The real work: Import the embedded JSON Data + $DefaultConfig = (ConvertFrom-Json @paramConvertFromJson) + #endregion DefaultConfig +} + +process +{ + #region ExistingConfig + #region Splat + $paramTestPath = @{ + Path = ($BaseChromeProfilePath + $ChromeProfile + '\Preferences') + ErrorAction = 'SilentlyContinue' + } + #endregion Splat + + if (Test-Path @paramTestPath) + { + # Import the existing config + try + { + #region Splat + $paramGetContent = @{ + Path = ($BaseChromeProfilePath + $ChromeProfile + '\Preferences') + Raw = $true + ErrorAction = $STP + Encoding = $Encoding + Force = $true + } + + $paramConvertFromJson = @{ + InputObject = (Get-Content @paramGetContent ) + ErrorAction = $STP + } + #endregion Splat + + # The real work: Import the JSON Data + $ChromePreferences = (ConvertFrom-Json @paramConvertFromJson) + } + catch + { + #region Splat + $paramWriteError = @{ + Message = 'Unable to load the configuration file' + Category = 'ReadError' + ErrorAction = $STP + } + #endregion Splat + + Write-Error @paramWriteError + } + } + else + { + <# + No existing config found + Create en empty object + #> + $ChromePreferences = @{ + } + } + #endregion ExistingConfig + + #region ValueVariables + # The existing configuration + $ChromePreferencesValues = ($ChromePreferences.psobject.Properties | Where-Object -FilterScript { + $_.MemberType -eq 'NoteProperty' + }) + + # The recommended configuration + $DefaultConfigValues = ($DefaultConfig.psobject.Properties | Where-Object -FilterScript { + $_.MemberType -eq 'NoteProperty' + }) + #endregion ValueVariables + + #region RecommendedValues + # Fill in the new Defaults + foreach ($Property in $DefaultConfigValues) + { + try + { + #region Splat + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = $Property.Name + Value = $Property.Value + ErrorAction = $STP + } + #endregion Splat + + # Add the configuration value + $null = ($NewConfig | Add-Member @paramAddMember) + } + catch + { + #region Splat + $paramWriteWarning = @{ + Message = ('Unable to set recommended value for {0}' -f $Property.Name) + } + #endregion Splat + + Write-Warning @paramWriteWarning + } + } + #endregion RecommendedValues + + #region ExistingValues + # Add the old config values + foreach ($Property in $ChromePreferencesValues) + { + try + { + #region Splat + $paramAddMember = @{ + MemberType = 'NoteProperty' + Name = $Property.Name + Value = $Property.Value + ErrorAction = $STP + } + #endregion Splat + + # Add the configuration value + $null = ($NewConfig | Add-Member @paramAddMember) + } + catch + { + #region Splat + $paramWriteVerbose = @{ + Message = ('The value of {0} was replaced' -f $Property.Name) + } + #endregion Splat + + Write-Verbose @paramWriteVerbose + } + } + #endregion ExistingValues +} + +end +{ + if ($pscmdlet.ShouldProcess(($BaseChromeProfilePath + $ChromeProfile + '\Preferences'), 'Save')) + { + #region SaveTheNewPreferences + # Save the Preferences + try + { + #region Splat + $paramConvertToJson = @{ + Depth = 100 + Compress = $true + } + + $paramSetContent = @{ + Path = ($BaseChromeProfilePath + $ChromeProfile + '\Preferences') + Value = ($NewConfig | ConvertTo-Json @paramConvertToJson ) + Force = $true + Encoding = $Encoding + ErrorAction = $STP + } + #endregion Splat + + # Save the new Chrome configuration file + $null = (Set-Content @paramSetContent) + } + catch + { + #region Splat + $paramWriteError = @{ + Message = 'Unable to save the new configuration file' + Category = 'WriteError' + ErrorAction = $STP + } + #endregion Splat + + Write-Error @paramWriteError + } + #endregion SaveTheNewPreferences + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Set-IPv6InWindows.ps1 b/Powershell/PowerShell-collection/Misc/Set-IPv6InWindows.ps1 new file mode 100644 index 0000000..2ec8f96 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Set-IPv6InWindows.ps1 @@ -0,0 +1,347 @@ +function Set-IPv6InWindows +{ + <# + .SYNOPSIS + Configuring the IPv6 value in windows the registry + + .DESCRIPTION + Configuring the IPv6 value in windows the registry + Based on the Microsoft Information, Microsoft KB929852, RFC 3484, and RFC 4291 + + .PARAMETER Force + Forces the cmdlet to set a property on items that cannot otherwise be accessed by the user. + + .PARAMETER Value + Specifies the value of the property. + + .EXAMPLE + PS C:\> Set-IPv6InWindows -Value 0 -WhatIf + + Enable all IPv6 components + + .EXAMPLE + PS C:\> Set-IPv6InWindows -Value 32 -verbose + + Prefer IPv4 over IPv6 will be set, with a verbose output + + .LINK + Get-IPv6InWindows + + .LINK + https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows + + .LINK + https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/configure-ipv6-in-windows#reference + + .NOTES + Next version might also support test inputs instead of the numbers (Dec). + This is just a quick and dirty initial version! + + Want to knwo what is set in your registry? Use its companion Get-IPv6InWindows + #> + [CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] + [OutputType([string])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [ValidateSet('32', '17', '16', '1', '10', '8', '4', '2', '255', '0')] + [Alias('IPv6Configuration', 'IPv6Config')] + [int] + $Value = 0, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [switch] + $Force + ) + + begin + { + #region BoundParameters + if (($PSCmdlet.MyInvocation.BoundParameters['Force']).IsPresent) + { + $IsForced = $true + } + else + { + $IsForced = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + { + $IsVerbose = $true + } + else + { + $IsVerbose = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) + { + $IsDebug = $true + } + else + { + $IsDebug = $false + } + #endregion BoundParameters + + #region ValueSwitch + switch ($Value) + { + 0 + { + $ValueText = ('Enable all IPv6 components ({0})' -f $Value) + } + 255 + { + $ValueText = ('Disable all IPv6 components ({0})' -f $Value) + + Write-Warning -Message 'This is not recommended, Think about 32 (Prefer IPv4 over IPv6) instead.' + } + 2 + { + $ValueText = ('Disable 6to4 ({0})' -f $Value) + } + 4 + { + $ValueText = ('Disable ISATAP ({0})' -f $Value) + } + 8 + { + $ValueText = ('Disable Teredo ({0})' -f $Value) + } + 10 + { + $ValueText = ('Disable Teredo and 6to4 ({0})' -f $Value) + } + 1 + { + $ValueText = ('Disable all tunnel interfaces ({0})' -f $Value) + } + 16 + { + $ValueText = ('Disable all LAN and PPP interfaces ({0})' -f $Value) + } + 17 + { + $ValueText = ('Disable all LAN, PPP and tunnel interfaces ({0})' -f $Value) + } + 32 + { + $ValueText = ('Prefer IPv4 over IPv6 ({0})' -f $Value) + } + default + { + $paramWriteError = @{ + Exception = ('Unknown value found: {0}' -f $Value) + Message = ('Sorry, but this cmdlet does NOT support the value {0}' -f $Value) + Category = 'OperationStopped' + CategoryActivity = 'Please check the supported values' + TargetObject = $Value + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + } + } + + Write-Verbose -Message ('New IPv6 configuration: {0}' -f $ValueText) + #endregion ValueSwitch + + # Get the Value from the registry + $paramGetItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\tcpip6\Parameters' + Name = 'DisabledComponents' + Debug = $IsDebug + Verbose = $IsVerbose + ErrorAction = 'Continue' + WarningAction = 'Continue' + } + $ComponentValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty DisabledComponents) + + if ($Value -eq $ComponentValue) + { + # Don't go any further! + $paramWriteError = @{ + Exception = 'Old an new value are the same' + Message = 'The new value matches the existing IPv6 configuration!' + Category = 'OperationStopped' + CategoryActivity = 'No further action is required' + TargetObject = $Value + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + } + + #region + switch ($ComponentValue) + { + 0 + { + $ComponentValueText = ('All IPv6 components are enabled ({0})' -f $ComponentValue) + } + 255 + { + $ComponentValueText = ('All IPv6 components are disabled ({0})' -f $ComponentValue) + } + 2 + { + $ComponentValueText = ('6to4 is disabled ({0})' -f $ComponentValue) + } + 4 + { + $ComponentValueText = ('ISATAP is disabled ({0})' -f $ComponentValue) + } + 8 + { + $ComponentValueText = ('Teredo is disabled ({0})' -f $ComponentValue) + } + 10 + { + $ComponentValueText = ('Teredo and 6to4 is disabled ({0})' -f $ComponentValue) + } + 1 + { + $ComponentValueText = ('All tunnel interfaces are disabled ({0})' -f $ComponentValue) + } + 16 + { + $ComponentValueText = ('All LAN and PPP interfaces are disabled ({0})' -f $ComponentValue) + } + 17 + { + $ComponentValueText = ('All LAN, PPP and tunnel interfaces are disabled ({0})' -f $ComponentValue) + } + 32 + { + $ComponentValueText = ('Prefer IPv4 over IPv6 ({0})' -f $ComponentValue) + } + default + { + $ComponentValueText = ('Unknown value found: {0}' -f $ComponentValue) + + Write-Warning -Message $ComponentValueText + } + } + + Write-Verbose -Message ('Existing IPv6 configuration: {0}' -f $ComponentValueText) + #endregion + } + + process + { + if ($PSCmdlet.ShouldProcess('Existing IPv6 configuration', 'modify')) + { + try + { + $paramSetItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\tcpip6\Parameters' + Name = 'DisabledComponents' + Value = $Value + Force = $IsForced + Debug = $IsDebug + Verbose = $IsVerbose + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + Write-Verbose -Message $info + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + + # Get the Value from the registry + $ComponentValue = $null + $paramGetItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\tcpip6\Parameters' + Name = 'DisabledComponents' + Debug = $IsDebug + Verbose = $IsVerbose + ErrorAction = 'Continue' + WarningAction = 'Continue' + } + $ComponentValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty DisabledComponents) + + if ($Value -eq $ComponentValue) + { + Write-Verbose -Message 'New IPv6 configuration was applied' + } + else + { + # Don't go any further! + $paramWriteError = @{ + Exception = 'Unable to apply IPv6 configuration' + Message = ('New IPv6 configuration was NOT applied! You requested {0}, but the set is {1}' -f $ValueText, $ComponentValue) + Category = 'OperationStopped' + CategoryActivity = 'Please check the registry and your permissions' + TargetObject = $Value + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + } + } + } + + end + { + ('New IPv6 configuration is set to: {0}' -f $ValueText) + } +} +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Set-PowerPlanToHighPerformance.ps1 b/Powershell/PowerShell-collection/Misc/Set-PowerPlanToHighPerformance.ps1 new file mode 100644 index 0000000..209dff2 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Set-PowerPlanToHighPerformance.ps1 @@ -0,0 +1,114 @@ +#Requires -RunAsAdministrator + +<# + .SYNOPSIS + Set the Windows Power Plan to High Performance + + .DESCRIPTION + Set the Windows Power Plan to High Performance, it also disables Hibernation and System Standby + + .EXAMPLE + PS C:\> .\Set-PowerPlanToHighPerformance.ps1 + + .NOTES + Works fine on Windows Server 2016 (Developed for server use). + Should also work on Windows 10, but I never tested it on a Windows 10 system! +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +process +{ + #region Cleanup + $ActivePowerPlan = $null + $PowerPlanHighPowerState = $null + #endregion Cleanup + + #region InformationGathering + # Splat the parameters + $paramGetWmiObject = @{ + Namespace = 'root\cimv2\power' + Class = 'Win32_PowerPlan' + } + + # Gather the PowerPlan information + $ActivePowerPlan = (Get-WmiObject @paramGetWmiObject | Select-Object -Property ElementName, IsActive) + + # Filter the 'High Performance' plan info + $PowerPlanHighPowerState = $ActivePowerPlan | Where-Object -FilterScript { + $_.ElementName -eq 'High Performance' + } + #endregion InformationGathering + + #region CheckIfTheTweakIsNeeded + if ($PowerPlanHighPowerState.IsActive -ne $true) + { + # Use the PowerPlan "High Performance" + $paramGetWmiObject.Filter = "ElementName = 'High Performance'" + $powerPlan = (Get-WmiObject @paramGetWmiObject) + + #region ActivateThePowerPlan + $null = (Invoke-Command -ScriptBlock { + $powerPlan.Activate() + } -ErrorAction SilentlyContinue) + <# + This looks a bit crappy, but it works fine and I don't like to have any output of the activation + #> + #endregion ActivateThePowerPlan + } + #endregion CheckIfTheTweakIsNeeded + + #region Cleanup + $PowerPlanHighPowerState = $null + #endregion Cleanup + + #region Retest + $PowerPlanHighPowerState = $ActivePowerPlan | Where-Object -FilterScript { + $_.ElementName -eq 'High Performance' + } + + # Filter the 'High Performance' plan info + if ($PowerPlanHighPowerState.IsActive -ne $true) + { + Write-Warning -Message "Unable to set the PowerPlan to 'High Performance'" + } + #endregion Retest + + #region NoStandBy + & "$env:windir\system32\powercfg.cpl" -change -standby-timeout-ac 0 + #endregion NoStandBy + + #region DisableHibernationSupport + & "$env:windir\system32\powercfg.cpl" -change -hibernate-timeout-ac 0 + #endregion DisableHibernationSupport +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Set-PublishUserActivities.ps1 b/Powershell/PowerShell-collection/Misc/Set-PublishUserActivities.ps1 new file mode 100644 index 0000000..ab69f3b --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Set-PublishUserActivities.ps1 @@ -0,0 +1,117 @@ +function Set-PublishUserActivities +{ + <# + .SYNOPSIS + Enable or Disable the collection of Activity History + + .DESCRIPTION + Enable or Disable the collection of Activity History in Windows 10. The default is to disable it! + + .PARAMETER enable + Enable the collection of Activity History in Windows 10 + + .EXAMPLE + PS C:\> Set-PublishUserActivities + + Disable the collection of Activity History in Windows 10 + + .EXAMPLE + PS C:\> Set-PublishUserActivities -enable + + Enable the collection of Activity History in Windows 10 + + .NOTES + Quick and dirty function + + .LINK + https://lifehacker.com/windows-10-collects-activity-data-even-when-tracking-is-1831054394 + + .LINK + https://www.tenforums.com/tutorials/100341-enable-disable-collect-activity-history-windows-10-a.html#option2s2 + #> + [CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [switch] + $enable = $false + ) + + begin + { + $RegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System' + $RegistryName = 'PublishUserActivities' + + if ($enable) + { + $RegistryValue = '1' + $SetAction = 'Enable' + Write-Verbose -Message 'Enable the collection of Activity History' + } + else + { + $RegistryValue = '0' + $SetAction = 'Disable' + Write-Verbose -Message 'Disable the collection of Activity History' + } + } + + process + { + if ($pscmdlet.ShouldProcess('Collection of Activity History', $SetAction)) + { + try + { + $SetPublishUserActivitiesParams = @{ + Path = $RegistryPath + Name = $RegistryName + Value = $RegistryValue + PropertyType = 'DWORD' + Force = $true + Confirm = $false + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $null = (New-ItemProperty @SetPublishUserActivitiesParams) + Write-Verbose -Message 'Collection of Activity History value modified.' + } + catch + { + Write-Warning -Message 'Unable to modify the collection of Activity History value!' + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Test-IsAdmin.ps1 b/Powershell/PowerShell-collection/Misc/Test-IsAdmin.ps1 new file mode 100644 index 0000000..b9e4016 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Test-IsAdmin.ps1 @@ -0,0 +1,91 @@ +function Test-IsAdmin +{ + <# + .SYNOPSIS + Check if PowerShell run elevated (e.g. as admin or not) + + .DESCRIPTION + This is a complete new approach to check if the Shell runs elevated or not. + It runs on PowerShell and PowerShell Core, and it supports macOS or Linux as well. + + .EXAMPLE + PS C:\> Test-IsAdmin + + .NOTES + Rewritten function to support PowerShell Desktop and Core on Windows, macOS, and Linux + Mostly used within other functions and in the personal PowerShell profiles. + + Releasenotes: + 1.0.1 2019-05-09: Add some comments to the code + 1.0.0 2019-05-09: Initial Release of the rewritten function + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([bool])] + param () + + process + { + if ($PSVersionTable.PSEdition -eq 'Desktop') + { + # Fastest way on Windows + ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator') + } + elseif (($PSVersionTable.PSEdition -eq 'Core') -and ($PSVersionTable.Platform -eq 'Unix')) + { + # Ok, on macOS and Linux we use ID to figure out if we run elevated (0 means superuser rights) + if ((id -u) -eq 0) + { + return $true + } + else + { + return $false + } + } + elseif (($PSVersionTable.PSEdition -eq 'Core') -and ($PSVersionTable.Platform -eq 'Win32NT')) + { + # For PowerShell Core on Windows the same approach as with the Desktop work just fine + # This is for future improvements :-) + ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator') + } + else + { + # Unable to figure it out! + Write-Warning -Message 'Unknown' + + return + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Test-Port.ps1 b/Powershell/PowerShell-collection/Misc/Test-Port.ps1 new file mode 100644 index 0000000..fc4194b --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Test-Port.ps1 @@ -0,0 +1,371 @@ +function Test-Port +{ + <# + .SYNOPSIS + Tests port on a given computer. + + .DESCRIPTION + Tests port on computer. This functions supports both: TCP and UPD + + .PARAMETER computer + Name of server to test the port connection on. + + .PARAMETER port + Port to test + + .PARAMETER tcp + Use tcp port + + .PARAMETER udp + Use udp port + + .PARAMETER UDPTimeOut + Sets a timeout for UDP port query. (In milliseconds, Default is 1000) + + .PARAMETER TCPTimeOut + Sets a timeout for TCP port query. (In milliseconds, Default is 1000) + + .EXAMPLE + Test-Port -computer 'server' -port 80 + Checks port 80 on server 'server' to see if it is listening + + .EXAMPLE + 'server' | Test-Port -port 80 + Checks port 80 on server 'server' to see if it is listening + + .EXAMPLE + Test-Port -computer @("server1","server2") -port 80 + Checks port 80 on server1 and server2 to see if it is listening + + .EXAMPLE + Test-Port -computer dc1 -port 17 -udp -UDPtimeout 10000 + + Server : dc1 + Port : 17 + TypePort : UDP + Open : True + Notes : "My spelling is Wobbly. It's good spelling but it Wobbles, and the letters + get in the wrong places." A. A. Milne (1882-1958) + + Description + ----------- + Queries port 17 (qotd) on the UDP port and returns whether port is open or not + + .EXAMPLE + @("server1","server2") | Test-Port -port 80 + Checks port 80 on server1 and server2 to see if it is listening + + .EXAMPLE + (Get-Content hosts.txt) | Test-Port -port 80 + Checks port 80 on servers in host file to see if it is listening + + .EXAMPLE + Test-Port -computer (Get-Content hosts.txt) -port 80 + Checks port 80 on servers in host file to see if it is listening + + .EXAMPLE + Test-Port -computer (Get-Content hosts.txt) -port @(1..59) + Checks a range of ports from 1-59 on all servers in the hosts.txt file + + .NOTES + For TCP tests, you might want to use Test-NetConnection + But Test-NetConnection is unable to test UDP Ports + + Author: Boe Prox + DateCreated: 18Aug2010 + Contributor: Joerg Hochwald + + .LINK + https://boeprox.wordpress.org + + .LINK + http://jhochwald.com + + .LINK + http://www.iana.org/assignments/port-numbers + #> + [cmdletbinding( + DefaultParameterSetName = '', + ConfirmImpact = 'None' + )] + param ( + [Parameter( + Mandatory, HelpMessage = 'Name of server to test the port connection on.', + Position = 0, + ParameterSetName = '', + ValueFromPipeline)] + [array] + $computer, + [Parameter( + Position = 1, HelpMessage = 'Port to test', + Mandatory, + ParameterSetName = '')] + [array] + $port, + [Parameter( + ParameterSetName = '')] + [int] + $TCPtimeout = 1000, + [Parameter( + ParameterSetName = '')] + [int] + $UDPtimeout = 1000, + [Parameter( + ParameterSetName = '')] + [switch] + $TCP, + [Parameter( + ParameterSetName = '')] + [switch] + $UDP + ) + + begin + { + # Check if we test TCP or UDP + if ((-not $TCP) -AND (-not $UDP)) + { + <# + Nothing? OK, we use the Defualt (TCP) + #> + $TCP = $True + } + + <# + Typically you never do this, but in this case I felt it was for the benefit of the function as any errors will be noted in the output of the report + It also reduce the handling within the code. Smart, right? + #> + $ErrorActionPreference = 'SilentlyContinue' + + # Cleanup + $report = @() + } + + process + { + foreach ($c in $computer) + { + foreach ($p in $port) + { + if ($TCP) + { + # Create temporary holder + # TODO: Replace this + $temp = '' | Select-Object -Property Server, Port, TypePort, Open, Notes + + # Create object for connecting to port on computer + $tcpobject = (New-Object -TypeName system.Net.Sockets.TcpClient) + + # Connect to remote machine's port + $connect = $tcpobject.BeginConnect($c, $p, $null, $null) + + # Configure a timeout before quitting + $wait = $connect.AsyncWaitHandle.WaitOne($TCPtimeout, $False) + + # If timeout + if (-not $wait) + { + # Close connection + $tcpobject.Close() + + Write-Verbose -Message 'Connection Timeout' + + # Build report + $temp.Server = $c + $temp.Port = $p + $temp.TypePort = 'TCP' + $temp.Open = $False + $temp.Notes = 'Connection to Port Timed Out' + } + else + { + $error.Clear() + $null = $tcpobject.EndConnect($connect) + + # If error + if ($error[0]) + { + # Begin making error more readable in report + [string]$string = ($error[0].exception).message + $message = (($string.split(':')[1]).replace('"', '')).TrimStart() + $failed = $True + } + + # Close connection + $tcpobject.Close() + + # If unable to query port to due failure + if ($failed) + { + # Build report + $temp.Server = $c + $temp.Port = $p + $temp.TypePort = 'TCP' + $temp.Open = $False + $temp.Notes = "$message" + } + else + { + # Build report + $temp.Server = $c + $temp.Port = $p + $temp.TypePort = 'TCP' + $temp.Open = $True + $temp.Notes = '' + } + } + + # Reset failed value + $failed = $null + + # Merge temp array with report + $report += $temp + } + + if ($UDP) + { + # Create temporary holder + $temp = '' | Select-Object -Property Server, Port, TypePort, Open, Notes + + # Create object for connecting to port on computer + $udpobject = (New-Object -TypeName system.Net.Sockets.Udpclient) + + # Set a timeout on receiving message + $udpobject.client.ReceiveTimeout = $UDPtimeout + + # Connect to remote machine's port + Write-Verbose -Message 'Making UDP connection to remote server' + + $udpobject.Connect("$c", $p) + + # Sends a message to the host to which you have connected. + Write-Verbose -Message 'Sending message to remote host' + + $a = (New-Object -TypeName system.text.asciiencoding) + $byte = $a.GetBytes("$(Get-Date)") + $null = $udpobject.Send($byte, $byte.length) + + # IPEndPoint object will allow us to read datagrams sent from any source. + Write-Verbose -Message 'Creating remote endpoint' + + $remoteendpoint = (New-Object -TypeName system.net.ipendpoint -ArgumentList ([ipaddress]::Any, 0)) + + try + { + # Blocks until a message returns on this socket from a remote host. + Write-Verbose -Message 'Waiting for message return' + + $receivebytes = $udpobject.Receive([ref]$remoteendpoint) + [string]$returndata = $a.GetString($receivebytes) + + if ($returndata) + { + Write-Verbose -Message 'Connection Successful' + + # Build report + $temp.Server = $c + $temp.Port = $p + $temp.TypePort = 'UDP' + $temp.Open = $True + $temp.Notes = $returndata + $udpobject.close() + } + } + catch + { + if ($error[0].ToString() -match '\bRespond after a period of time\b') + { + # Close connection + $udpobject.Close() + + # Make sure that the host is online and not a false positive that it is open + if (Test-Connection -ComputerName $c -Count 1 -Quiet) + { + Write-Verbose -Message 'Connection Open' + + # Build report + $temp.Server = $c + $temp.Port = $p + $temp.TypePort = 'UDP' + $temp.Open = $True + $temp.Notes = '' + } + else + { + <# + It is possible that the host is not online or that the host is online, + but ICMP is blocked by a firewall and this port is actually open. + #> + + Write-Verbose -Message 'Host maybe unavailable' + + # Build report + $temp.Server = $c + $temp.Port = $p + $temp.TypePort = 'UDP' + $temp.Open = $False + $temp.Notes = 'Unable to verify if port is open or if host is unavailable.' + } + } + elseif ($error[0].ToString() -match 'forcibly closed by the remote host') + { + # Close connection + $udpobject.Close() + + Write-Verbose -Message 'Connection Timeout' + + # Build report + $temp.Server = $c + $temp.Port = $p + $temp.TypePort = 'UDP' + $temp.Open = $False + $temp.Notes = 'Connection to Port Timed Out' + } + else + { + $udpobject.close() + } + } + # Merge temp array with report + $report += $temp + } + } + } + } + + end + { + # Generate Report + $report + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Test-ValidEmail.ps1 b/Powershell/PowerShell-collection/Misc/Test-ValidEmail.ps1 new file mode 100644 index 0000000..12c21ed --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Test-ValidEmail.ps1 @@ -0,0 +1,78 @@ +function Test-ValidEmail +{ + <# + .SYNOPSIS + Simple Function to check if a String is a valid Mail + + .DESCRIPTION + Simple Function to check if a String is a valid Mail and return a Bool + + .PARAMETER address + Address String to Check + + .OUTPUT + Bool + + .INPUT + String + + .EXAMPLE + # Not a valid String + PS C:\> Test-ValidEmail -address 'Joerg.Hochwald' + False + + .EXAMPLE + # Valid String + PS C:\> Test-ValidEmail -address 'Joerg.Hochwald@outlook.com' + True + + .NOTES + Disclaimer: The code is provided 'as is,' with all possible faults, defects or errors, and without warranty of any kind. + + Author: Joerg Hochwald + #> + [OutputType([bool])] + param + ( + [Parameter(Mandatory, + HelpMessage = 'Address String to Check')] + [ValidateNotNullOrEmpty()] + [string] + $address + ) + + process + { + ($address -as [mailaddress]).Address -eq $address -and $address -ne $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Transfer_PSGallery_Installed_Modules.ps1 b/Powershell/PowerShell-collection/Misc/Transfer_PSGallery_Installed_Modules.ps1 new file mode 100644 index 0000000..d78cfcb --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Transfer_PSGallery_Installed_Modules.ps1 @@ -0,0 +1,281 @@ +#requires -Version 2.0 -Modules PowerShellGet -RunAsAdministrator + +<# + .SYNOPSIS + Import/export all Modules installed from a repository + + .DESCRIPTION + Import/export all Modules installed from a repository + The Import option itries to install the modules. + Perfect for clones of existing existing systems. + + .PARAMETER Export + Export the List of Modules installed via given repository + + .PARAMETER Import + Import the List and installs all Modules via given repository + + .PARAMETER Path + File used to handle the Import/Export + + .PARAMETER Repository + The repository to use. The default is the PowerShell Gallery + + .EXAMPLE + PS C:\> .\Transfer_Repository_Installed_Modules.ps1 -Export -Path 'C:\Temp\list.txt' + + .EXAMPLE + PS C:\> .\Transfer_Repository_Installed_Modules.ps1 -Export -Path 'C:\Temp\list.txt' -Repository 'Internal' + + .EXAMPLE + PS C:\> .\Transfer_Repository_Installed_Modules.ps1 -Import -Path 'C:\Temp\list.txt' + + .EXAMPLE + PS C:\> .\Transfer_Repository_Installed_Modules.ps1 -Import -Path 'C:\Temp\list.txt' -Repository 'Internal' + + .NOTES + Releasenotes: + 1.0.0 2019-03-07: Internal Release + 1.0.1 2019-03-10: Initial Version with Repository Support + + THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER. + + Dependencies: + PowerShellGet + Elevated Shell + + .LINK + https://aka.ms/InstallModule +#> +[CmdletBinding(DefaultParameterSetName = 'Import', + ConfirmImpact = 'None')] +param +( + [Parameter(ParameterSetName = 'Export', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [switch] + $Export, + [Parameter(ParameterSetName = 'Import', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [switch] + $Import, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [string] + $Path = 'C:\Tools\list.txt', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2)] + [ValidateNotNullOrEmpty()] + [string] + $Repository = 'PSGallery' +) + +begin +{ + # Set some defaults + $STP = 'Stop' + $CNT = 'Continue' + + if (-not $Repository) + { + $Repository = 'PSGallery' + } + + if (-not $Path) + { + $Path = 'C:\Tools\list.txt' + } +} + +process +{ + if ($Export) + { + Write-Verbose -Message 'Start the export job' + + try + { + # Some Modules throw an error! + Write-Verbose -Message 'Get a list of modules' + + $AllInstalledModule = (Get-InstalledModule -ErrorAction SilentlyContinue -WarningAction $CNT | Where-Object -FilterScript { + $_.Repository -eq $Repository + } | Select-Object -ExpandProperty name) + + # Export the List to a given File + Write-Verbose -Message 'Export the Module information' + + $paramSetContent = @{ + Value = $AllInstalledModule + Path = $Path + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $CNT + } + $null = (Set-Content @paramSetContent) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message $info.Exception -ErrorAction $STP + + return + } + } + elseif ($Import) + { + Write-Verbose -Message 'Start the import job' + + try + { + Write-Verbose -Message 'Read the list of modules' + + $paramGetContent = @{ + Path = $Path + Force = $true + ErrorAction = $STP + WarningAction = $CNT + } + $AllInstalledModule = (Get-Content @paramGetContent) + + Write-Verbose -Message 'Try to install the Modules' + + foreach ($SingleInstalledModule in $AllInstalledModule) + { + Write-Verbose -Message ('Try to find {0} on {1}' -f $SingleInstalledModule, $Repository) + + $FindTheModule = $null + + try + { + # It a bit slower if we search for it first, but this should make the installation more robust + $paramFindModule = @{ + Name = $SingleInstalledModule + Repository = $Repository + ErrorAction = $STP + WarningAction = $CNT + } + $FindTheModule = (Find-Module @paramFindModule) + + if ($FindTheModule) + { + Write-Verbose -Message ('Try to install {0} from {1}' -f $SingleInstalledModule, $Repository) + + try + { + $paramInstallModule = @{ + Name = $SingleInstalledModule + Repository = $Repository + SkipPublisherCheck = $true + AllowClobber = $true + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $CNT + } + $null = (Install-Module @paramInstallModule) + } + catch + { + Write-Warning -Message ('Found {0} in {1}, but could NOT install it!' -f $SingleInstalledModule, $Repository) -ErrorAction $CNT -WarningAction $CNT + } + } + else + { + Write-Warning -Message ('Unable to find {0} in {1}?' -f $SingleInstalledModule, $Repository) -ErrorAction $CNT -WarningAction $CNT + } + } + catch + { + Write-Warning -Message ('Something went wrong with {0} in {1}?' -f $SingleInstalledModule, $Repository) -ErrorAction $CNT -WarningAction $CNT + } + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Error -Message $info.Exception -ErrorAction $STP + + return + } + } + else + { + Write-Error -Message 'Unknown action specified.' -Category InvalidArgument -RecommendedAction 'Check parameter' -ErrorAction $STP + + return + } +} + +end +{ + Write-Verbose -Message 'Have a great day!' +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Tweak_UDPforFastSend.ps1 b/Powershell/PowerShell-collection/Misc/Tweak_UDPforFastSend.ps1 new file mode 100644 index 0000000..a1a5adb --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Tweak_UDPforFastSend.ps1 @@ -0,0 +1,59 @@ +# Increases the UDP packet size to 1500 bytes for FastSend +# http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2040065 +$blnIncreaseFastSendDatagramThreshold = $true + +if ($blnIncreaseFastSendDatagramThreshold) +{ + #Inform user + Write-Output -InputObject 'Increasing UDP FastSend threshold' + + $RegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\AFD\Parameters' + $RegistryName = 'FastSendDatagramThreshold' + $RegistryValue = '1500' + + If (Test-Path -Path $RegistryPath) + { + $null = (New-ItemProperty -Path $RegistryPath -Name $RegistryName -Value $RegistryValue -PropertyType DWORD -Force -Confirm:$false) + Write-Output -InputObject '(CREATED)' + } + else + { + $null = (Set-ItemProperty -Path $RegistryPath -Name $RegistryName -Value $RegistryValue -Force -Confirm:$false) + Write-Output -InputObject '(MODIFIED)' + } +} +else +{ + Write-Warning -Message '(skipped)' +} + +# Set multiplication factor to the default UDP scavenge value (MaxEndpointCountMult) +# http://support.microsoft.com/kb/2685007/en-us +$lbnSetMaxEndpointCountMult = $true + +if ($lbnSetMaxEndpointCountMult) +{ + #Inform user + Write-Output -InputObject 'Set multiplication factor to the default UDP scavenge value' + + $RegistryPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\BFE\Parameters' + $RegistryName = 'MaxEndpointCountMult' + $RegistryValue = '0x10' + + If (Test-Path -Path $RegistryPath) + { + $null = (New-ItemProperty -Path $RegistryPath -Name $RegistryName -Value $RegistryValue -PropertyType DWORD -Force -Confirm:$false) + + Write-Output -InputObject '(CREATED)' + } + else + { + $null = (Set-ItemProperty -Path $RegistryPath -Name $RegistryName -Value $RegistryValue -Force -Confirm:$false) + + Write-Output -InputObject '(MODIFIED)' + } +} +else +{ + Write-Warning -Message '(skipped)' +} diff --git a/Powershell/PowerShell-collection/Misc/UnixTimeStampTools.ps1 b/Powershell/PowerShell-collection/Misc/UnixTimeStampTools.ps1 new file mode 100644 index 0000000..c21164a --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/UnixTimeStampTools.ps1 @@ -0,0 +1,247 @@ +function ConvertFrom-UnixTimeStamp +{ + <# + .SYNOPSIS + Converts a Timestamp (Epochdate) into Datetime + + .DESCRIPTION + Converts a Timestamp (Epochdate) into Datetime + + .PARAMETER TimeStamp + Timestamp (Epochdate) + + .PARAMETER Milliseconds + Is the given Timestamp (Epochdate) in Miliseconds instead of Seconds? + + .EXAMPLE + PS C:\> ConvertFrom-UnixTimeStamp -TimeStamp 1547839380 + + Converts a Timestamp (Epochdate) into Datetime + + .EXAMPLE + PS C:\> ConvertFrom-UnixTimeStamp -TimeStamp 1547839380712 -Milliseconds + + Converts a Timestamp (Epochdate) into Datetime, given value is in Milliseconds + + .NOTES + Added the 'UniFi' (Alias for the switch 'Milliseconds') because the API returns miliseconds instead of seconds + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([datetime])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + Position = 0, + HelpMessage = 'Timestamp (Epochdate)')] + [ValidateNotNullOrEmpty()] + [Alias('Epochdate')] + [long] + $TimeStamp, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('UniFi')] + [switch] + $Milliseconds = $false + ) + + begin + { + # Set some defaults + $UnixStartTime = '1/1/1970' + + # Cleanup + $Result = $null + } + + process + { + try + { + if ($Milliseconds) + { + $Result = ((Get-Date -Date $UnixStartTime -ErrorAction Stop -WarningAction SilentlyContinue).AddMilliseconds($TimeStamp)) + } + else + { + try + { + $Result = ((Get-Date -Date $UnixStartTime -ErrorAction Stop -WarningAction SilentlyContinue).AddSeconds($TimeStamp)) + } + catch + { + # Try a Fallback! + $Result = ((Get-Date -Date $UnixStartTime -ErrorAction Stop -WarningAction SilentlyContinue).AddMilliseconds($TimeStamp)) + } + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + } + } + + end + { + $Result + } +} + +function ConvertTo-UnixTimeStamp +{ + <# + .SYNOPSIS + Converts a Datetime into a Unix Timestamp (Epochdate) + + .DESCRIPTION + Converts a Datetime into a Unix Timestamp (Epochdate) + + .PARAMETER Date + The Date String that should be converted, default is now (if none is given) + + .PARAMETER Milliseconds + Should the Timestamp (Epochdate) in Miliseconds instead of Seconds? + + .EXAMPLE + PS C:\> ConvertTo-UnixTimeStamp + + Converts the actual time into a Unix Timestamp (Epochdate) + + .EXAMPLE + PS C:\> ConvertTo-UnixTimeStamp -Milliseconds + + Converts the actual time into a Unix Timestamp (Epochdate), in milliseconds + + .EXAMPLE + PS C:\> ConvertTo-UnixTimeStamp -Date ((Get-Date).AddDays(-1)) + + Covert the same time yesterday into a Unix Timestamp (Epochdate) + + .EXAMPLE + PS C:\> ConvertTo-UnixTimeStamp -Date ((Get-Date).AddDays(-1)) -Milliseconds + + Covert the same time yesterday into a Unix Timestamp (Epochdate), in milliseconds + + .NOTES + Added the 'UniFi' (Alias for the switch 'Milliseconds') because the API returns milliseconds instead of seconds + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([long])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [Alias('TimeStamp', 'DateTimeStamp')] + [datetime] + $Date = (Get-Date), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('UniFi')] + [switch] + $Milliseconds = $false + ) + + begin + { + # Set some defaults + $UnixStartTime = '1/1/1970' + + # Cleanup + $Result = $null + } + + process + { + try + { + if ($Milliseconds) + { + $Result = ([long]((New-TimeSpan -Start (Get-Date -Date $UnixStartTime -ErrorAction Stop -WarningAction SilentlyContinue) -End (Get-Date -Date $Date -ErrorAction Stop -WarningAction SilentlyContinue) -ErrorAction Stop -WarningAction SilentlyContinue).TotalMilliseconds)) + } + else + { + $Result = ([long]((New-TimeSpan -Start (Get-Date -Date $UnixStartTime -ErrorAction Stop -WarningAction SilentlyContinue) -End (Get-Date -Date $Date -ErrorAction Stop -WarningAction SilentlyContinue) -ErrorAction Stop -WarningAction SilentlyContinue).TotalSeconds)) + } + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + } + } + + end + { + $Result + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/Update-ModuleFromPSGallery.ps1 b/Powershell/PowerShell-collection/Misc/Update-ModuleFromPSGallery.ps1 new file mode 100644 index 0000000..89f2c38 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/Update-ModuleFromPSGallery.ps1 @@ -0,0 +1,156 @@ +#requires -Version 3.0 -Modules PowerShellGet + +function Update-ModuleFromPSGallery +{ + <# + .SYNOPSIS + Update a given PowerShell Module with the latest version from the Gallery + + .DESCRIPTION + Update a given PowerShell Module with the latest version from the Gallery, if needed + + .PARAMETER ModuleName + Name of the PowerShell Module + + .EXAMPLE + PS C:\> Update-ModuleFromPSGallery -ModuleName 'PowerShellGet' + + Check if an update for 'PowerShellGet' is needed, if a newer version is available it will install it + + .EXAMPLE + PS C:\> 'PowerShellGet' | Update-ModuleFromPSGallery + + Check if an update for 'PowerShellGet' is needed, if a newer version is available it will install it + + .EXAMPLE + PS C:\> Get-InstalledModule -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Update-ModuleFromPSGallery -ErrorAction Continue -WarningAction SilentlyContinue + + Check if an update for for any Gallery Module is needed, if a newer version is available it will install it + + .NOTES + Just a quick an dirty function to keep a given Module up-to-date + + If you want to update any system-wide installed module, you need to start this elevated (Run as admin) + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Name of the PowerShell Module')] + [ValidateNotNullOrEmpty()] + [Alias('Module', 'Name')] + [string[]] + $ModuleName + ) + + begin + { + $InstalledModuleInfo = $null + $InstalledVersion = $null + $OnlineVersion = $null + $ModuleScope = $null + } + + process + { + foreach ($SingleModuleName in $ModuleName) + { + if (Get-InstalledModule -Name $SingleModuleName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue) + { + # unload the module + $null = (Remove-Module -Name $SingleModuleName -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue) + + # Get the Info about the module (local) + $InstalledModuleInfo = (Get-Module -Name $SingleModuleName -ListAvailable -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Select-Object -Property Version, ModuleBase) + + # Save the Version Info + [Version]$InstalledVersion = (($InstalledModuleInfo).Version) + + # Get the Info about the module from the Gallery + [Version]$OnlineVersion = (Find-Module -Name $SingleModuleName -Repository PSGallery -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Select-Object -ExpandProperty Version) + + if ($InstalledVersion -lt $OnlineVersion) + { + if ((($InstalledModuleInfo).ModuleBase) -like ((($InstalledModuleInfo).ModuleBase) + '*')) + { + $ModuleScope = 'AllUsers' + } + else + { + $ModuleScope = 'CurrentUser' + } + + try + { + Write-Verbose -Message ('[TRY] Update: {0}' -f $SingleModuleName) + + $null = (Update-Module -Name $SingleModuleName -Scope $ModuleScope -ErrorAction Stop -WarningAction Continue -Force) + + Write-Verbose -Message ('[SUCCESS] Update: {0}' -f $SingleModuleName) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message ('[FAILED] Update: {0}' -f $SingleModuleName) + } + } + } + } + } + + end + { + $InstalledModuleInfo = $null + $InstalledVersion = $null + $OnlineVersion = $null + $ModuleScope = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/invoke-CPUWorkload.ps1 b/Powershell/PowerShell-collection/Misc/invoke-CPUWorkload.ps1 new file mode 100644 index 0000000..ea99df6 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/invoke-CPUWorkload.ps1 @@ -0,0 +1,139 @@ +#requires -Version 3.0 -Modules CimCmdlets + +<# + .SYNOPSIS + Simple script to generate a lot of CPU load + + .DESCRIPTION + Generate a lot of CPU load based on the number logical processors + + .PARAMETER Overload + Double the number of jobs. + Normally the script will start one job per logical Processors, + this switch will double the number. This will overload the server. + + Hint: If your server supports Hyper-threading, + the number of logical Processors is the doubled amount of cores! + + WARNING: The system might become unstable! + + .EXAMPLE + PS C:\> .\invoke-CPUWorkload.ps1 + + .NOTES + Nothing fancy, just a plain and easy script to generate a lot of load. + Created to do a stress test on new servers. +#> +[CmdletBinding(ConfirmImpact = 'Medium')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('Double')] + [switch] + $Overload +) + +#region ClearRunningCPUWorkloadJobs +function Clear-RunningCPUWorkloadJobs +{ + <# + .SYNOPSIS + Get, stop, and remove all running CPUWorkloadJobs + + .DESCRIPTION + Get, stop, and remove all running CPUWorkloadJobs + + .EXAMPLE + PS C:\> Clear-RunningCPUWorkloadJobs + + .NOTES + Internal Helper for the "Generate a log of CPU load" script + #> + + [CmdletBinding(ConfirmImpact = 'Low')] + param () + + # Get a list of running jobs + $CPUWorkloadJobList = (Get-Job -Name 'CPUWorkload_*' -ErrorAction SilentlyContinue) + + # Cleanup + if ($CPUWorkloadJobList) + { + $null = ($CPUWorkloadJobList | Stop-Job -ErrorAction SilentlyContinue) + $null = ($CPUWorkloadJobList | Receive-Job -AutoRemoveJob -Wait -ErrorAction SilentlyContinue) + } +} +#endregion ClearRunningCPUWorkloadJobs + +# Get the number of logical processors +[int]$NumThreads = (Get-CimInstance -ClassName Win32_Processor | Select-Object -ExpandProperty NumberOfLogicalProcessors) + +if (($PSCmdlet.MyInvocation.BoundParameters['Overload']).IsPresent) +{ + $NumThreads = ($NumThreads * 2) + + Write-Warning -Message 'You decide to overload the system! This may cause the system to become unstable.' +} + +# Stop and cleanup, if needed +$null = (Clear-RunningCPUWorkloadJobs) + +# Start to generate load, based on the system capabilities +foreach ($loop in 1 .. $NumThreads) +{ + $null = (Start-Job -Name ('CPUWorkload_' + $loop) -ScriptBlock { + [float]$result = 1 + + while ($true) + { + [float]$x = Get-Random -Minimum 1 -Maximum 999999999 + + $result = $result * $x + } + }) +} + +<# + We start the work with Start-Job (in the background) + If this can cause an overload, the system might become unstable and it might take very long to respond. + + CTRL+C will not end background execution of worker threads, it will just kill this script +#> +Read-Host -Prompt 'Press any key to exit the test.' + +# Stop and cleanup, if needed +$null = (Clear-RunningCPUWorkloadJobs) + +# Ensure all jobs are gone +$null = (Clear-RunningCPUWorkloadJobs) + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/invoke-GetDSCResources.ps1 b/Powershell/PowerShell-collection/Misc/invoke-GetDSCResources.ps1 new file mode 100644 index 0000000..88ab355 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/invoke-GetDSCResources.ps1 @@ -0,0 +1,198 @@ +#requires -Modules PowerShellGet -Version 2.0 -RunAsAdministrator + +<# + .SYNOPSIS + Install some DSC Resources + + .DESCRIPTION + Getting, install, or update DSC Resources I want to have. + It could be used to install every Module from the Gallery. + However, this is something I do with DSC afterwards! + + .EXAMPLE + PS C:\> .\invoke-GetDSCResources.ps1 + + .EXAMPLE + PS C:\> .\invoke-GetDSCResources.ps1 -verbose + VERBOSE: Populating RepositorySourceLocation property for module PSDscResources. + VERBOSE: Try to update PSDscResources + VERBOSE: Updated PSDscResources + + .NOTES + Small script I created for myself. + I have to prepare DSC systems from time to time, and I want to have the same set of DSC resources on all of them. + Mainly because I'm lazy, but I'm an old-school Unix guy: Never type something more than two times: AUTOMATE. + + I install the resources system wide! + That is why we have the Elevated Shell requirement (#Requires -RunAsAdministrator). + If you want to use it just for the current user, change the Scope in $paramInstallModule from 'AllUsers' to 'CurrentUser'. + + TODO: Pester Test is missing + DONE: Make it more robust + + Disclaimer: The code is provided 'as is,' with all possible faults, defects or errors, and without warranty of any kind. + + Author: Joerg Hochwald + + .LINK + Author http://jhochwald.com +#> +[CmdletBinding()] +param () + +begin +{ + # Define some defaults + $STP = 'Stop' + $SC = 'SilentlyContinue' + + # Suppressing the PowerShell Progress Bar + $script:ProgressPreference = $SC + + # Create a list of the DSC Resources I want + $NewDSCModules = @( + 'PSDscResources', + 'xNetworking', + 'xPSDesiredStateConfiguration', + 'xWebAdministration', + 'xCertificate', + 'xComputerManagement', + 'xActiveDirectory', + 'SystemLocaleDsc', + 'xRemoteDesktopAdmin', + 'xPendingReboot', + 'xSmbShare', + 'xWindowsUpdate', + 'xDscDiagnostics', + 'xCredSSP', + 'xDnsServer', + 'xWinEventLog', + 'xDhcpServer', + 'xHyper-V', + 'xStorage', + 'xWebDeploy' + 'xRemoteDesktopSessionHost', + 'xDismFeature', + 'xSystemSecurity', + 'WebAdministrationDsc', + 'OfficeOnlineServerDsc', + 'AuditPolicyDsc', + 'xDFS', + 'SecurityPolicyDsc', + 'xReleaseManagement', + 'xExchange', + 'xDefender', + 'xWindowsEventForwarding', + 'cHyper-V' + ) +} + +process +{ + foreach ($NewDSCModule in $NewDSCModules) + { + # Cleanup + $ModuleIsAvailable = $null + + # Check: Do I have the resource? + $paramGetModule = @{ + ListAvailable = $true + Name = $NewDSCModule + ErrorAction = $SC + WarningAction = $SC + } + $ModuleIsAvailable = (Get-Module @paramGetModule) + + if (-not ($ModuleIsAvailable)) + { + # Nope: Install the resource + try + { + Write-Verbose -Message ('Try to install {0}' -f $NewDSCModule) + + $paramInstallModule = @{ + Name = $NewDSCModule + Scope = AllUsers + Force = $true + ErrorAction = $STP + WarningAction = $SC + } + $null = (Install-Module @paramInstallModule) + + Write-Verbose -Message ('Installed {0}' -f $NewDSCModule) + } + catch + { + # Whoopsie + $paramWriteWarning = @{ + Message = ('Sorry, unable to install {0}' -f $NewDSCModule) + ErrorAction = $SC + } + Write-Warning @paramWriteWarning + } + } + else + { + try + { + Write-Verbose -Message ('Try to update {0}' -f $NewDSCModule) + + # TODO: Implement the check from invoke-ModuleUpdates.ps1 to prevent the unneeded update tries. + $paramUpdateModule = @{ + Name = $NewDSCModule + Confirm = $false + ErrorAction = $STP + WarningAction = $SC + } + $null = (Update-Module @paramUpdateModule) + + Write-Verbose -Message ('Updated {0}' -f $NewDSCModule) + } + catch + { + # Whoopsie + $paramWriteWarning = @{ + Message = ('Sorry, unable to update {0}' -f $NewDSCModule) + ErrorAction = $SC + } + Write-Warning @paramWriteWarning + } + } + } +} + +end +{ + # No longer suppressing the PowerShell Progress Bar + $script:ProgressPreference = 'Continue' +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Misc/invoke-ModuleMaint.ps1 b/Powershell/PowerShell-collection/Misc/invoke-ModuleMaint.ps1 new file mode 100644 index 0000000..505f251 --- /dev/null +++ b/Powershell/PowerShell-collection/Misc/invoke-ModuleMaint.ps1 @@ -0,0 +1,120 @@ +#Requires -Version 3.0 -Modules PowerShellGet -RunAsAdministrator + +<# + .SYNOPSIS + PowerShell Module maintenance + + .DESCRIPTION + Quick and dirty script that removes all older versions of all installed PowerShell Modules. + + .EXAMPLE + PS C:\> .\invoke-ModuleMaint.ps1 + + # Removes all old versions for all installed PowerShell Modules. + + .NOTES + Why: + I do an automated update of my Modules, this process just updates straight to the latest and + greatest version of each installed module. I ended up with a bunch of older version for most + Modules, and I needed something to clean this up. + + I found several stuff that does the same thing, but they all use "Get-InstalledModule" and the + performance of this command is terrible! I have to use "Uninstall-Module" that is slow enough, + so I needed something that runs faster on my system, where I have a lot of Modules installed. + + Please note: + This will try to remove all older versions of all installed powerShell versions. + There might be issues with newer versions, so be aware of that. + There is no check, just a simple removal off all older versions. +#> +[CmdletBinding()] +param () + +begin +{ + # Get all Modules with every Version that the system knows about. + $AllModules = (Get-Module -ListAvailable -Refresh) +} + +process +{ + # Now we initiate a loop over the information we have. + foreach ($SingleModule in $AllModules) + { + # Get the detailed information for the Module + $paramGetModule = @{ + ListAvailable = $true + Name = $SingleModule.name + } + $SingleInstance = (Get-Module @paramGetModule) + + # Do we have more than one installed version? + if ($SingleInstance -is [array]) + { + # What is the latest and greatest? + $latest = (($SingleInstance | Sort-Object -Property Version -Descending)[0]).Version + + # Now loop over all older versions + foreach ($VersionToRemove in $SingleInstance) + { + if (($VersionToRemove.Version -lt $latest)) + { + try + { + # This is damn slow, but it is the safest way to do it! + $paramUninstallModule = @{ + Name = $VersionToRemove.Name + RequiredVersion = $VersionToRemove.Version + Force = $true + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + Confirm = $false + } + $null = (Uninstall-Module @paramUninstallModule) + } + catch + { + # TODO: Check if we need something here. Or do we just want to catch it? + Write-Verbose -Message 'Whoops' + } + } + } + } + } +} + +end +{ + # TODO: Check if we need something here. + Write-Verbose -Message 'We are done, have a nice day!' +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/ConditionalAccessNamedLocationToolingForGraph.ps1 b/Powershell/PowerShell-collection/Office365/ConditionalAccessNamedLocationToolingForGraph.ps1 new file mode 100644 index 0000000..9711590 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/ConditionalAccessNamedLocationToolingForGraph.ps1 @@ -0,0 +1,1030 @@ +#requires -Version 3.0 +<# + .SYNOPSIS + Update a Conditional access named location with the new external (public) IP address + + .DESCRIPTION + Update a Conditional access named location with the new external (public) IP address. + Since my router disconnects from time to time, this was something I needed badly! + + .EXAMPLE + PS C:\> .\ConditionalAccessNamedLocationToolingForGraph.ps1 + + .NOTES + Additional information about the file. +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + #region Configuration + # Where to store the cache file + $ToolPath = 'c:\temp\' + + # The application (client) ID for your AzureAD app, e.g. b7ca6bb8-4a3f-465d-ace2-8e8aae841162 + $ClientId = '' + + # The application (client) secret (password) for your AzureAD app, e.g. Mnq(eL9Wd83(8w^roBu4 + $ClientSecret = '' + + # Your AzureAD Domain + # Valid is: + # contoso.onmicrosoft.com + # contoso.com + # The ID (e.g. 09f89b81-0707-4f46-a6d2-c1989d515067) + $TenantName = '' + + # The ID of the location you want to check/update, e.g. 5a28f1e1-7b97-4b0c-8f08-793a4fec7ea5 + $LocationID = '' + + # Cache the Location info on the local disk? (this is highly recommended) + $CacheLocationInfo = $true + + # Cache File name (Json) + $CacheLocationInfoFile = '' + + # To you want to store the token in a global varable? + $CacheToken = $true + #endregion Configuration + + #region HelperFunctions + function Compare-LocationInformation + { + <# + .SYNOPSIS + Compare the external address with the existing location information + + .DESCRIPTION + Compare the external address with the existing location information + + .PARAMETER ReferenceObject + The location IP Address + + .PARAMETER DifferenceObject + The new IP external IP address + + .EXAMPLE + PS C:\> Compare-LocationInformation -ReferenceObject $value1 -DifferenceObject $value2 + True + + Compare the external address with the existing location information and they match + + .EXAMPLE + PS C:\> Compare-LocationInformation -ReferenceObject $value1 -DifferenceObject $value2 + False + + Compare the external address with the existing location information and they do NOT match + + .NOTES + Only the .net ipaddress class is supported. So not use any other format here (e.g. String) + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([bool])] + param + ( + [Parameter(Mandatory, HelpMessage = 'The location IP Address', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [Alias('ExistingIP')] + [ipaddress] + $ReferenceObject, + [Parameter(Mandatory, HelpMessage = 'The new IP external IP address', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [Alias('ExternalIP')] + [ipaddress] + $DifferenceObject + ) + + begin + { + # The default + [bool]$Result = $false + } + + process + { + if ($ReferenceObject -eq $DifferenceObject) + { + [bool]$Result = $true + } + else + { + [bool]$Result = $false + } + } + + end + { + # Dump the info to the console + $Result + } + } + + function Get-MSGraphAuthenticationToken + { + <# + .SYNOPSIS + This function is used to get an authentication token for the Graph API REST interface + + .DESCRIPTION + This function uses the application (client) ID and application secret to get an authentication token for the Microsoft Graph API REST interface + + .PARAMETER ClientId + The application (client) ID that you will get in the AzureAD Application Center + + .PARAMETER ClientSecret + The Client Secret that you will get in the AzureAD Application Center + + .PARAMETER TenantName + The Directory (tenant) ID, Domain, or Tenant Name. + + Valid input is: + The tenant name: contoso.onmicrosoft.com + The directory (tenant) ID: 8076c776-6780-4e95-b62a-7e5581d159e7 + Any registered tenant domain: contoso.com + + .EXAMPLE + PS C:\> Get-MSGraphAuthenticationToken -ClientId '8076c776-6780-4e95-b62a-7e5581d159e7' -ClientSecret 'U975D^o9iv5()(4*' -TenantName 'c24d4a92-a38f-433f-807f-5d2a1a20bd49' + + Get the access token + + .EXAMPLE + $paramGetMSGraphAuthenticationToken = @{ + ClientId = '8076c776-6780-4e95-b62a-7e5581d159e7' + ClientSecret = 'U975D^o9iv5()(4*' + TenantName = 'c24d4a92-a38f-433f-807f-5d2a1a20bd49' + } + PS C:\> $GraphAccessToken = (Get-MSGraphAuthenticationToken @paramGetMSGraphAuthenticationToken) + + Get the Access Token, same as above with splated parameters + + .NOTES + Only application (client) ID and application secret are supported here! + If you want to use any other method to get the token, please modify or replace the function. + I prefer to use a certificate, but in this special case, I decided to go with application (client) ID and application secret! + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(Mandatory, HelpMessage = 'The Application (client) ID that you will get in the AzureAD Application Center', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('ApplicationID')] + [string] + $ClientId, + [Parameter(Mandatory, HelpMessage = 'The Client Secret that you will get in the AzureAD Application Center', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [string] + $ClientSecret, + [Parameter(Mandatory, HelpMessage = 'The Directory (tenant) ID, Domain, or Tenant Name.', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('TenantID', 'DirectoryID')] + [string] + $TenantName + ) + + begin + { + # Purpose of the access token + $ResourceValue = 'https://graph.microsoft.com/' + + # Splat the request body element + $AuthRequestBody = @{ + Grant_Type = 'client_credentials' + Scope = ($ResourceValue + '.default') + client_Id = $ClientId + Client_Secret = $ClientSecret + } + + # Cleanup + $AccessToken = $null + } + + process + { + try + { + $paramInvokeRestMethod = @{ + Uri = ('https://login.microsoftonline.com/' + $TenantName + '/oauth2/v2.0/token') + Method = 'POST' + Body = $AuthRequestBody + ErrorAction = 'Stop' + } + $AccessToken = (Invoke-RestMethod @paramInvokeRestMethod) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + # Dump the info to the console + $AccessToken + } + } + + function Get-MSGraphconditionalAccessNamedLocation + { + <# + .SYNOPSIS + Get the conditional access named location, all or single + + .DESCRIPTION + Get the conditional access named location, all or single via Microsoft Graph Call + + .PARAMETER GraphAccessToken + The access token for the Microsoft Graph API Call + + .PARAMETER Location + Get one location instead of all locations? + If you want just one, you have to specify the ID of the location here, Names are not (yet) supported. + This might come in a future version of the function. + + .EXAMPLE + PS C:\> Get-MSGraphconditionalAccessNamedLocation -GraphAccessToken $GraphAccessToken + + Get all conditional access named location + + .EXAMPLE + PS C:\> Get-MSGraphconditionalAccessNamedLocation -GraphAccessToken $GraphAccessToken - Location $LocationID + + Get one conditional access named location + + .EXAMPLE + PS C:\> Get-MSGraphconditionalAccessNamedLocation -GraphAccessToken $GraphAccessToken - Location '06abccd1-7ed4-4b63-894e-c2b323345b72' + + Get one conditional access named location + + .EXAMPLE + $paramGetMSGraphconditionalAccessNamedLocation = @{ + GraphAccessToken = $GraphAccessToken + Location = $LocationID + } + PS C:\> Get-MSGraphconditionalAccessNamedLocation @paramGetMSGraphconditionalAccessNamedLocation + + Get one conditional access named location + + .NOTES + Maybe the next verion work with a filter to get locations by name + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(Mandatory, HelpMessage = 'The Access Token for the Graph Call', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('MsGraphAccessToken', 'AccessToken')] + [psobject] + $GraphAccessToken, + [Parameter(ParameterSetName = 'SingleLocation', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('SingleLocation')] + [string] + $Location + ) + + begin + { + if (-not ($GraphAccessToken)) + { + $paramWriteError = @{ + Message = 'The Access Token is missing' + Exception = 'The Access Token is missing' + Category = 'ObjectNotFound' + TargetObject = $GraphAccessToken + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + } + + $BaseURI = 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations/' + + switch ($PsCmdlet.ParameterSetName) + { + 'SingleLocation' + { + $BaseURI = $BaseURI + $Location + } + } + } + + process + { + # Cleanup + $Result = $null + + # Splat the parameters + $paramInvokeRestMethod = @{ + Headers = @{ + Authorization = ('Bearer ' + $GraphAccessToken.access_token) + } + Uri = $BaseURI + Method = 'Get' + } + + $Result = (Invoke-RestMethod @paramInvokeRestMethod) + } + + end + { + # Dump the info to the console + $Result + } + } + + function Start-WaitLoop + { + <# + .SYNOPSIS + Wrapper for Start-Sleep that use minutes instead of seconds + + .DESCRIPTION + Simple wrapper for the regular Start-Sleep cmdlet that use minutes instead of seconds. + + .PARAMETER Minutes + The Number of minutes to wait + + .PARAMETER Hours + The number of hours to wait + + .EXAMPLE + PS C:\> Start-WaitLoop + + Waits 5 minutes, this is the default + + .EXAMPLE + PS C:\> Start-WaitLoop -Hours 1 + + Waits one hour + + .EXAMPLE + PS C:\> Start-WaitLoop -Minutes + + Waits 15 minutes + + .NOTES + If you do not pass any parameter, it will wait 5 minutes! + #> + [CmdletBinding(DefaultParameterSetName = 'MinutesToWait', + ConfirmImpact = 'None')] + param + ( + [Parameter(ParameterSetName = 'MinutesToWait', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('min')] + [int] + $Minutes = 5, + [Parameter(ParameterSetName = 'HoursToWait', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('hrs')] + [int] + $Hours = 1 + ) + + begin + { + # Cleanup + $SleepTimer = $null + + # Any parameters? + switch ($PsCmdlet.ParameterSetName) + { + 'MinutesToWait' + { + if (-not ($Minutes)) + { + [int]$Minutes = 5 + } + [int]$SleepTimer = $Minutes * 60 + } + 'HoursToWait' + { + if (-not ($Hours)) + { + $paramWriteError = @{ + Message = 'Sorry, with the Hours value you have to specify something!' + TargetObject = $Hours + ErrorAction = 'Stop' + Exception = 'Sorry, with the Hours value you have to specify something!' + Category = 'ObjectNotFound' + } + Write-Error @paramWriteError + } + [int]$SleepTimer = $Hours * 3600 + } + default + { + [int]$SleepTimer = 300 + } + } + } + + process + { + $paramStartSleep = @{ + Seconds = $SleepTimer + } + $null = (Start-Sleep @paramStartSleep) + } + + end + { + # Cleanup + $SleepTimer = $null + } + } + + function Start-HandleCacheLocationInfo + { + <# + .SYNOPSIS + Check if the location info is cached and get it if it exists + + .DESCRIPTION + Check if the location info is cached and get it if it exists + + .PARAMETER Path + Where to find the location Info + + .EXAMPLE + PS C:\> Start-HandleCacheLocationInfo -Path '.\CacheObject.json' + + Check if the location info is cached and get it if it exists + + .NOTES + The warning will be removed in the next version + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(Mandatory, HelpMessage = 'Where to find the location Info', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('LocationInfoFile')] + [string] + $Path + ) + + begin + { + # Cleanup + $Result = $null + } + + process + { + $paramTestPath = @{ + Path = $Path + ErrorAction = 'SilentlyContinue' + } + if (-not (Test-Path @paramTestPath)) + { + # Cleanup + $Result = $null + + # This will be removed in the next version + Write-Warning -Message 'Given Cache File does NOT exist!' + } + else + { + try + { + # Get the cache file content + $paramGetContent = @{ + Path = $Path + Force = $true + Encoding = 'UTF8' + ErrorAction = 'Stop' + } + $RawJson = (Get-Content @paramGetContent) + + # convert the json content to a PSObject + $paramConvertFromJson = @{ + ErrorAction = 'Stop' + } + $Result = ($RawJson | ConvertFrom-Json @paramConvertFromJson) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + } + + end + { + # Dump the info to the console + $Result + } + } + + function Get-ExternalIpAddress + { + <# + .SYNOPSIS + Return your external IP address from a given service + + .DESCRIPTION + Return your external IP address from a given service + + .PARAMETER Service + Service to use to get your external IP address + + .EXAMPLE + PS C:\> Get-ExternalIpAddress + + Return your external IP address from 'https://ip.enatec.net/ip' + + .EXAMPLE + PS C:\> Get-ExternalIpAddress -Service 'https://ipinfo.io/ip' + + Return your external IP address from a given service + + .NOTES + Helper function to get the external ip address via a given web service + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([ipaddress])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [ValidateSet('https://ipinfo.io/ip', 'https://ifconfig.me/ip', 'https://ip.enatec.net/ip', IgnoreCase = $true)] + [Alias('ServiceURI', 'ServiceURL')] + [string] + $Service = 'https://ip.enatec.net/ip' + ) + + begin + { + # Cleanup + $Result = $null + } + + process + { + try + { + # Request the info from the given service / We also extract the IP only + $paramInvokeWebRequest = @{ + Uri = $Service + ErrorAction = 'Stop' + } + [IPAddress]$Result = ((Invoke-WebRequest @paramInvokeWebRequest).Content).Trim() + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + } + + end + { + # Dump the info to the console + $Result + } + } + + function Get-AcctualConditionalAccessNamedLocationIp + { + <# + .SYNOPSIS + Extract the IP address from the conditional access named location object + + .DESCRIPTION + Extract the IP address from the conditional access named location object + + .PARAMETER Object + The conditional access named location object from the Microsoft Graph call or from the local cache. + + .EXAMPLE + PS C:\> Get-AcctualConditionalAccessNamedLocationIp -Object $ConditionalAccessNamedLocationOject + + Extract the IP address from the conditional access named location object $ConditionalAccessNamedLocationOject + + .NOTES + Helper function + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([ipaddress])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'The conditional access named location object from the Microsoft Graph call or from the local cache.')] + [ValidateNotNullOrEmpty()] + [Alias('ConditionalAccessNamedLocationInfo')] + [pscustomobject] + $Object + ) + + begin + { + # Cleanup + $Result = $null + } + process + { + # Exctract the IP address + [String]$Result = ($Object.ipRanges | Select-Object -ExpandProperty cidrAddress) + + # Mangle the object to remove the CIDR part (should be /32) + [IPAddress]$Result = (($Result -split '/')[0]) + } + + end + { + # Dump the info to the console + $Result + } + } + + function Set-MSGraphConditionalAccessNamedLocation + { + <# + .SYNOPSIS + Modify the conditional access named location via Microsoft Graph + + .DESCRIPTION + Modify the conditional access named location via Microsoft Graph. + It will update the IP Address + + .PARAMETER GraphAccessToken + The access token for the Graph Call + + .PARAMETER Location + The location obect (cached or from the API call + + .PARAMETER UpdatedIP + The new external IP Address + + .PARAMETER + A description of the parameter. + + .EXAMPLE + PS C:\> Set-MSGraphConditionalAccessNamedLocation -GraphAccessToken $GraphAccessToken -Location $CachedLocationInfoData -UpdatedIP $ActIP + + Modify the conditional access named location via Microsoft Graph, the Token is stored in the $GraphAccessToken, + the location in $CachedLocationInfoData, and the new ip in $ActIP + + .EXAMPLE + $paramSetMSGraphConditionalAccessNamedLocation = @{ + GraphAccessToken = $GraphAccessToken + Location = $CachedLocationInfoData + UpdatedIP = $ActIP + } + PS C:\> Set-MSGraphConditionalAccessNamedLocation @paramSetMSGraphConditionalAccessNamedLocation + + Modify the conditional access named location via Microsoft Graph, the Token is stored in the $GraphAccessToken, + the location in $CachedLocationInfoData, and the new ip in $ActIP + + .NOTES + There is no feedback in any kind. + #> + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'The Access Token for the Graph Call')] + [ValidateNotNullOrEmpty()] + [Alias('MsGraphAccessToken', 'AccessToken')] + [psobject] + $GraphAccessToken, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'The Location Obect (Cached or from the API call')] + [ValidateNotNullOrEmpty()] + [Alias('SingleLocation')] + [psobject] + $Location, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2, + HelpMessage = 'The new external UP Address')] + [ValidateNotNullOrEmpty()] + [Alias('NewIP', 'ExternalIP')] + [ipaddress] + $UpdatedIP + ) + + begin + { + if (-not ($GraphAccessToken)) + { + $paramWriteError = @{ + Message = 'The Access Token is missing' + Exception = 'The Access Token is missing' + Category = 'ObjectNotFound' + TargetObject = $GraphAccessToken + ErrorAction = 'Stop' + } + Write-Error @paramWriteError + } + + # Extract the location ID + $LocationID = (($Location).id) + + # URI to call + $BaseURI = 'https://graph.microsoft.com/beta/identity/conditionalAccess/namedLocations/' + $LocationID + + # Extract the IP address + [String]$UpdatedIP = (($UpdatedIP).IPAddressToString).Trim() + } + + process + { + # Modify the location object + $Location.ipRanges | ForEach-Object { + if ($_ -match '/32') + { + # Change to the new address in Sigle IP CIDR (fixed value only) + $_.cidrAddress = ($UpdatedIP + '/32') + } + } + + $paramConvertToJson = @{ + InputObject = $Location + Compress = $true + } + $paramInvokeRestMethod = @{ + Headers = @{ + Authorization = ('Bearer ' + $GraphAccessToken.access_token) + 'Content-type' = 'application/json' + } + Uri = $BaseURI + Method = 'Patch' + Body = (ConvertTo-Json @paramConvertToJson) + } + + if ($PsCmdlet.ShouldProcess('Conditional Access Named Locations', 'Update via Microsoft Graph')) + { + $null = (Invoke-RestMethod @paramInvokeRestMethod) + } + } + } + #endregion HelperFunctions +} + +process +{ + #region ExecuteLogic + try + { + # Do we need a new access token? + if (-not ($GraphAccessToken)) + { + # Splat the parameters + $paramGetMSGraphAuthenticationToken = @{ + ClientId = $ClientId + ClientSecret = $ClientSecret + TenantName = $TenantName + } + # Get the access token + $GraphAccessToken = (Get-MSGraphAuthenticationToken @paramGetMSGraphAuthenticationToken) + + if ($CacheToken -eq $true) + { + $Global:GraphAccessToken = $GraphAccessToken + } + } + + # Cleanup + $CachedLocationInfoData = $null + + # Are we using caching? + if (($CacheLocationInfo -eq $true) -and ($CacheLocationInfoFile)) + { + # Call the Helper function to handle the cache + $paramStartHandleCacheLocationInfo = @{ + Path = ($ToolPath + $CacheLocationInfoFile) + } + $CachedLocationInfoData = (Start-HandleCacheLocationInfo @paramStartHandleCacheLocationInfo) + } + + # Do we have any cached infos? + if (-not ($CachedLocationInfoData)) + { + # Get the Location we want + $paramGetMSGraphconditionalAccessNamedLocation = @{ + GraphAccessToken = $GraphAccessToken + Location = $LocationID + } + $CachedLocationInfoData = (Get-MSGraphconditionalAccessNamedLocation @paramGetMSGraphconditionalAccessNamedLocation) + + + # Cache the Info ? + if (($CacheLocationInfo -eq $true) -and ($CacheLocationInfoFile)) + { + # Covert the object to JSON and store it in a local file + $paramConvertToJson = @{ + InputObject = $CachedLocationInfoData + Compress = $true + } + $paramNewItem = @{ + Path = ($ToolPath + $CacheLocationInfoFile) + Force = $true + } + $null = (ConvertTo-Json @paramConvertToJson | New-Item @paramNewItem) + } + } + + # Remove Objects that might cause issues later + try + { + $CachedLocationInfoData.PSObject.Properties.Remove('@odata.context') + $CachedLocationInfoData.PSObject.Properties.Remove('createdDateTime') + $CachedLocationInfoData.PSObject.Properties.Remove('modifiedDateTime') + } + catch + { + Write-Verbose -Message 'Whoopsie' + } + + # Cleanup + $ActIP = $null + $MyTrustedIP = $null + + # Get the external IP address + $paramGetExternalIpAddress = @{ + Service = 'https://ipinfo.io/ip' + } + [ipaddress]$ActIP = (Get-ExternalIpAddress @paramGetExternalIpAddress) + + # Get the conditional access named location IP value + $paramGetAcctualConditionalAccessNamedLocationIp = @{ + Object = $CachedLocationInfoData + } + [IPAddress]$MyTrustedIP = (Get-AcctualConditionalAccessNamedLocationIp @paramGetAcctualConditionalAccessNamedLocationIp) + + # Compare the objects we have + $paramCompareLocationInformation = @{ + ReferenceObject = $MyTrustedIP + DifferenceObject = $ActIP + } + if ((Compare-LocationInformation @paramCompareLocationInformation) -eq $false) + { + # Update the conditional access named location entry with the latest external IP + $null = (Set-MSGraphConditionalAccessNamedLocation -GraphAccessToken $GraphAccessToken -Location $CachedLocationInfoData -UpdatedIP $ActIP) + + if (($CacheLocationInfo -eq $true) -and ($CacheLocationInfoFile)) + { + # Remove the cache file + $paramRemoveItem = @{ + Path = ($ToolPath + $CacheLocationInfoFile) + Force = $true + Confirm = $false + } + $null = (Remove-Item @paramRemoveItem) + + # Get the location we want + $paramGetMSGraphconditionalAccessNamedLocation = @{ + GraphAccessToken = $GraphAccessToken + Location = $LocationID + } + $CachedLocationInfoData = (Get-MSGraphconditionalAccessNamedLocation @paramGetMSGraphconditionalAccessNamedLocation) + + # Remove Objects that might cause issues later + try + { + $CachedLocationInfoData.PSObject.Properties.Remove('@odata.context') + $CachedLocationInfoData.PSObject.Properties.Remove('createdDateTime') + $CachedLocationInfoData.PSObject.Properties.Remove('modifiedDateTime') + } + catch + { + Write-Verbose -Message 'Whoopsie' + } + + # Save the info + $paramConvertToJson = @{ + InputObject = $CachedLocationInfoData + Compress = $true + } + $paramNewItem = @{ + Path = ($ToolPath + $CacheLocationInfoFile) + Force = $true + } + $null = (ConvertTo-Json @paramConvertToJson | New-Item @paramNewItem) + } + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + break + #endregion ErrorHandler + } + #endregion ExecuteLogic +} diff --git a/Powershell/PowerShell-collection/Office365/Convert-HolidayFromApiToCsAutoAttendantHolidays.ps1 b/Powershell/PowerShell-collection/Office365/Convert-HolidayFromApiToCsAutoAttendantHolidays.ps1 new file mode 100644 index 0000000..b840953 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Convert-HolidayFromApiToCsAutoAttendantHolidays.ps1 @@ -0,0 +1,406 @@ +<# + .SYNOPSIS + Get German Holidays via API and export them to CSV for Skype for Business (Online). + + .DESCRIPTION + Get German Holidays via API and export them to CSV for Skype for Business (Online). + We use the German service feiertage-api.de to fetch the list, that is a great wrapper for the German Holidays published on Wikipedia. + + .PARAMETER State + The german state + https://de.wikipedia.org/wiki/Feiertage_in_Deutschland + + .PARAMETER Year + The Year to get and export from the API + Default is a acctual year (2019 while writing this) + + .PARAMETER appendyear + Append the Year to the Holliday string? + The Default is YES + + .PARAMETER Path + Specifies the path to the CSV file to export. + Default is Holidays.csv in your User Profile Home. + + .EXAMPLE + .\Convert-HolidayFromApiToCsAutoAttendantHolidays.ps1 + + Get German Holidays via API and export them to CSV for Skype for Business (Online). We use all the defaults! + + .EXAMPLE + .\Convert-HolidayFromApiToCsAutoAttendantHolidays.ps1 -State 'BY' -Year 2019 -path 'C:\Imports\Holidays.csv' + $bytes = [IO.File]::ReadAllBytes('C:\Imports\Holidays.csv') + Import-CsAutoAttendantHolidays -Identity 6283d913-8093-4951-8f46-c5912972002b -Input $bytes + + Get German Holidays via API and export them to 'C:\Imports\Holidays.csv'. We then convert it into Bytes (how Skype for Business likes it) and import them into Skype for Business. + + .NOTES + The Holiday break will begin at 5pm the day before the actual Holiday and will end the following day at 9am. + Please check if this match with your workflow and requirements!!! + + Only German Holidays are supported by the script and the API + Only Skype for Business Online is tested! I use it with a native Microsoft Teams environment, but you need to use the Skype for Business Online PowerShell Module to import it. + + If you like this, please support the feiertage-api.de project with a donation! + + I switched from https://www.spiketime.de/feiertagapi to https://feiertage-api.de/api/ with the latest version. The output was a bit better on the other API, but this API seems to be actively maintained. + + .LINK + https://feiertage-api.de + + .LINK + https://www.spiketime.de/blog/spiketime-feiertag-api-feiertage-nach-bundeslandern/ + + .LINK + Import-CsAutoAttendantHolidays + + .LINK + Export-CsAutoAttendantHolidays + + .LINK + Invoke-RestMethod + + .LINK + ConvertTo-Csv + + .LINK + Set-Content +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [ValidateSet('BW', 'BY', 'BE', 'BB', 'HB', 'HH', 'HE', 'MV', 'NI', 'NW', 'RP', 'SL', 'SN', 'ST', 'SH', 'TH', 'Baden-Württemberg', 'Baden-Wuerttemberg', 'Baden Württemberg', 'Baden Wuerttemberg', 'Bayern', 'Berlin', 'Brandenburg', 'Bremen', 'Hamburg', 'Hessen', 'Mecklenburg-Vorpommern', 'Mecklenburg Vorpommern', 'Niedersachsen', 'Nordrhein Westfalen', 'Nordrhein-Westfalen', 'Rheinland-Pfalz', 'Rheinland Pfalz', 'Saarland', 'Sachsen', 'Rheinland PfalzSachen-Anhalt', 'Schleswig-Holstein', 'Schleswig Holstein', 'Thüringen', 'Thueringen', IgnoreCase = $true)] + [string] + $State = 'HE', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [int] + $Year = (Get-Date).ToString('yyyy'), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [switch] + $appendyear, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('Export', 'ExportCSV', 'CsvFile')] + [string] + $Path = "$env:USERPROFILE\Holidays.csv" +) + +begin +{ + #region Checks + if (-not $State) + { + $State = 'HE' + } + + if (-not $Year) + { + $Year = (Get-Date).ToString('yyyy') + } + + if (-not $Path) + { + $Path = "$env:USERPROFILE\Holidays.csv" + } + #endregion Checks + + #region StateHandler + # More fuzzy state support + switch ($State) + { + 'Baden-Württemberg' + { + $State = 'BW' + } + 'Baden-Wuerttemberg' + { + $State = 'BW' + } + 'Baden Württemberg' + { + $State = 'BW' + } + 'Baden Wuerttemberg' + { + $State = 'BW' + } + 'Bayern' + { + $State = 'BY' + } + 'Berlin' + { + $State = 'BE' + } + 'Brandenburg' + { + $State = 'BB' + } + 'Bremen' + { + $State = 'HB' + } + 'Hamburg' + { + $State = 'HH' + } + 'Hessen' + { + $State = 'HE' + } + 'Mecklenburg-Vorpommern' + { + $State = 'MV' + } + 'Mecklenburg Vorpommern' + { + $State = 'MV' + } + 'Niedersachsen' + { + $State = 'NI' + } + 'Nordrhein-Westfalen' + { + $State = 'NW' + } + 'Nordrhein Westfalen' + { + $State = 'NW' + } + 'Rheinland-Pfalz' + { + $State = 'RP' + } + 'Rheinland Pfalz' + { + $State = 'RP' + } + 'Saarland' + { + $State = 'SL' + } + 'Sachsen' + { + $State = 'SN' + } + 'Sachen-Anhalt' + { + $State = 'ST' + } + 'Sachen Anhalt' + { + $State = 'ST' + } + 'Schleswig-Holstein' + { + $State = 'SH' + } + 'Schleswig Holstein' + { + $State = 'SH' + } + 'Thüringen' + { + $State = 'TH' + } + 'Thueringen' + { + $State = 'TH' + } + default + { + # Good luck ;-) + $State = $State.ToUpper() + } + } + #endregion StateHandler + + # Create a new Object for the CSV + $CsvDataObject = @() + + # Build the URI + $FeiertagApiObjectUri = ('https://feiertage-api.de/api/?jahr=' + $Year + '&nur_land=' + ($State.ToUpper())) +} + +process +{ + # Splat the Parameters (Change the UserAgent if you want) + $paramInvokeRestMethod = @{ + Method = 'Get' + Uri = $FeiertagApiObjectUri + ErrorAction = 'Stop' + WarningAction = 'Continue' + UserAgent = 'enaTecParser/1.0 (+http://www.enatec.io)' + } + + # Use the API to get the List + try + { + $FeiertagApiObject = (Invoke-RestMethod @paramInvokeRestMethod) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + + foreach ($SingleFeiertagApiObject in $FeiertagApiObject.PsObject.Properties) + { + # Create a new Object + $MemberObject = (New-Object -TypeName PSObject) + + # Fill in the Values from the API Call + + $MemberObject | Add-Member -NotePropertyName Name -NotePropertyValue $(if ($appendyear) + { + ($SingleFeiertagApiObject.Name) + ' 2019' + } + else + { + ($SingleFeiertagApiObject.Name) + } + ) + $MemberObject | Add-Member -NotePropertyName StartDateTime1 -NotePropertyValue ((Get-Date -Date $SingleFeiertagApiObject.Value.datum).AddDays(-1).ToString('MM/dd/yyyy') + ' 17:00') + $MemberObject | Add-Member -NotePropertyName EndDateTime1 -NotePropertyValue ((Get-Date -Date $SingleFeiertagApiObject.Value.datum).AddDays(+1).ToString('MM/dd/yyyy') + ' 09:00') + # Add some useless rows to match the CSV object + $MemberObject | Add-Member -NotePropertyName StartDateTime2 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime2 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime3 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime3 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime4 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime4 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime5 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime5 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime6 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime6 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime7 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime7 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime8 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime8 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime9 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime9 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName StartDateTime10 -NotePropertyValue $null + $MemberObject | Add-Member -NotePropertyName EndDateTime10 -NotePropertyValue $null + + # Add to the CSV object + $CsvDataObject += $MemberObject + + # Cleanup + $MemberObject = $null + } + + # Create the CSV Object (We remove the Quotes to make it a perfect fit) and save it + try + { + $paramSetContent = @{ + Value = ($CsvDataObject | ConvertTo-Csv -UseCulture -NoTypeInformation | ForEach-Object { + $_.Replace('"', '') + }) + Path = $Path + Force = $true + Confirm = $false + ErrorAction = 'Stop' + } + $null = (Set-Content @paramSetContent) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + $info | Out-String | Write-Verbose + + Write-Error -Message ($info.Exception) -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } +} + +end +{ + Write-Verbose -Message ((Get-Content -Path $Path).ToString()) + + #region Cleanup + $State = $null + $Year = $null + $appendyear = $null + $Path = $null + $CsvDataObject = $null + $FeiertagApiObjectUri = $null + $paramInvokeRestMethod = $null + $FeiertagApiObject = $null + $info = $null + $MemberObject = $null + $paramSetContent = $null + #endregion Cleanup +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/ConvertFrom-SafeLinksURL.ps1 b/Powershell/PowerShell-collection/Office365/ConvertFrom-SafeLinksURL.ps1 new file mode 100644 index 0000000..513bf3d --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/ConvertFrom-SafeLinksURL.ps1 @@ -0,0 +1,194 @@ +function ConvertFrom-SafeLinksURL +{ + <# + .SYNOPSIS + Decode a ATP SafeLinks URL + + .DESCRIPTION + Decode a Office 365 Advanced Threat Protection SafeLinks URL + + .PARAMETER SafeLinksURL + The ATP SafeLinks URL that you want to decode into original URL + + .EXAMPLE + PS C:\> ConvertFrom-SafeLinksURL -SafeLinksURL 'https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fhochwald.net%2F&data=04%7C01%7Cjoerg%40hochwald.net%7C6944b67827e54648125508d884babf16%7Cb768b3c4dc4b445c94c0388882f966fb%7C0%7C0%7C637405284900251734%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=qPb0a6MdRNuAzMIyLPlQ9iHPAufxNRywP2kKi%2FIHs%2FA%3D&reserved=0' + + This will decode the given URL and return the original URL (https://hochwald.net/) + + .EXAMPLE + PS C:\> ConvertFrom-SafeLinksURL -SafeLinksURL 'https://jhochwald.com' + + This will fail, the provided string is not a valid ATP SafeLink URL + + .EXAMPLE + PS C:\> ConvertFrom-SafeLinksURL -SafeLinksURL 'https://eur03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fhochwald.net%2F&reserved=0' + + This will fail, the provided string is not a valid ATP SafeLink URL + + .NOTES + Basic PowerShell function to replace an outdated Ruby script + There is also a great web based solution for this approach: http://www.o365atp.com + + .LINK + https://gist.github.com/jhochwald/8c9a3ef448058502ed184512e586815f + + .LINK + http://www.o365atp.com + + .LINK + https://products.office.com/en-us/exchange/online-email-threat-protection + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([string])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'The ATP SafeLinks URL that you want to decode into original URL')] + [ValidateNotNullOrEmpty()] + [Alias('SafeLink')] + [uri] + $SafeLinksURL + ) + + begin + { + #region Defaults + $STP = 'Stop' + #endregion Defaults + + try + { + # Load the Web Assembly to decode the URL + $null = (Add-Type -AssemblyName System.Web) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + } + + + process + { + try + { + # Create a new Object with the decoded URL, we use the default Web Assembly here + $OriginalURL = [Web.HttpUtility]::UrlDecode($SafeLinksURL) + + # Check the URL object + if ($OriginalURL -match '.safelinks.protection.outlook.com\/\?url=.+&data=') + { + $OriginalURL = $Matches[$Matches.Count - 1] + + # The default value (&) is used to provide the data string + $OriginalURL = (($OriginalURL -Split '\?url=')[1] -Split '&data=')[0] + } + elseif ($OriginalURL -match '.safelinks.protection.outlook.com\/\?url=.+&data=') + { + $OriginalURL = $Matches[$Matches.Count - 1] + + # Does the object use & instead of & to provide the data string + $OriginalURL = (($OriginalURL -Split '\?url=')[1] -Split '&data=')[0] + } + else + { + $paramWriteError = @{ + Exception = 'Invalid SafeLinks URL provided' + Message = 'The URL provided die NOT look like a valid Office 365 Advanced Threat Protection SafeLink URL' + Category = 'InvalidData' + TargetObject = $SafeLinksURL + RecommendedAction = 'Check the provided URL' + ErrorAction = $STP + } + Write-Error @paramWriteError + } + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + } + + end + { + [string]$OriginalURL + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Convert_O365_SKUs_and_Services.ps1 b/Powershell/PowerShell-collection/Office365/Convert_O365_SKUs_and_Services.ps1 new file mode 100644 index 0000000..cef7b97 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Convert_O365_SKUs_and_Services.ps1 @@ -0,0 +1,544 @@ +#requires -Version 2.0 -Modules MSOnline + +<# + PowerShell Core (PWSH) is not supported, at least not yet + + # Easy way to install the MSOL Module, requires PowerShell 5 or PSGet + Install-Module -Name MSOnline + + I still use the old (MSOL) module, cause it works best at the moment. + I might convert more and more to the newer modules +#> + +#region HelperFunctions +function Get-ServicePlanFriendlyList +{ + <# + .SYNOPSIS + A hash table of Office 365 Service Plans and there Human understandable description + + .DESCRIPTION + Helper function to make the Office 365 Service Plans as returned from scripts understandable for humans + + .EXAMPLE + PS C:\> Get-ServicePlanFriendlyList + + .NOTES + Internal Helper + + Version: 2.1 - Latest List + Author: Joerg Hochwald + License: The 3-Clause BSD License + #> + [CmdletBinding()] + [OutputType([hashtable])] + param () + + begin + { + # Cleanup + $ServicePlanFriendlyList = $null + } + + process + { + # Build the HashTable + $ServicePlanFriendlyList = @{ + 'AAD_BASIC' = 'Azure Active Directory Basic' + 'AAD_PREMIUM' = 'Azure Active Directory Premium' + 'MFA_PREMIUM' = 'Azure Multi-Factor Authentication' + 'RMS_S_ENTERPRISE' = 'Azure Information Protection' + 'RMS_S_ENTERPRISE_GOV' = 'Azure Information Protection for Government' + 'SHAREPOINT_DUET_EDU' = 'Duet Online for Academics' + 'SHAREPOINT_DUET_GOV' = 'Duet Online for Government' + 'EXCHANGE_S_STANDARD' = 'Exchange Online (Plan 1)' + 'EXCHANGE_S_STANDARD_GOV' = 'Exchange Online (Plan 1 for Government)' + 'EXCHANGE_S_ENTERPRISE' = 'Exchange Online (Plan 2)' + 'EXCHANGE_S_ENTERPRISE_GOV' = 'Exchange Online (Plan 2 for Government)' + 'EXCHANGE_S_ARCHIVE' = 'Exchange Online Archiving' + 'EXCHANGE_S_ARCHIVE_GOV' = 'Exchange Online Archiving for Government' + 'EXCHANGE_S_DESKLESS' = 'Exchange Online Kiosk' + 'EXCHANGE_S_DESKLESS_GOV' = 'Exchange Online Kiosk for Government' + 'EOP_ENTERPRISE' = 'Exchange Online Protection' + 'EOP_ENTERPRISE_GOV' = 'Exchange Online Protection for Government' + 'INTUNE_A' = 'Intune' + 'MCOIMP' = 'Skype for Business Online (formerly Lync Online (Plan 1)' + 'MCOIMP_GOV' = 'Skype for Business Online (Plan 1 for Government)' + 'MCOSTANDARD' = 'Skype for Business Online (Plan 2)' + 'MCOSTANDARD_GOV' = 'Skype for Business Online (Plan 2 for Government)' + 'MCOVOICECONF' = 'Skype for Business Online (Plan 3)' + 'MCOVOICECONF_GOV' = 'Skype for Business Online (Plan 3 for Government)' + 'CRMENTERPRISE' = 'Microsoft Dynamics CRM Online Enterprise' + 'CRMSTANDARD_GCC' = 'Microsoft Dynamics CRM Online Government Professional' + 'CRMSTANDARD' = 'Microsoft Dynamics CRM Online Professional' + 'DMENTERPRISE' = 'Microsoft Dynamics Marketing Online Enterprise' + 'MDM_SALES_COLLABORATION' = 'Microsoft Dynamics Marketing Sales Collaboration' + 'SQL_IS_SSIM' = 'Microsoft Power BI Information Services Plan 1' + 'BI_AZURE_P1' = 'Microsoft Power BI Reporting and Analytics Plan 1' + 'BI_AZURE_P2' = 'Microsoft Power BI Reporting and Analytics Plan 2' + 'NBENTERPRISE' = 'Microsoft Social Listening Enterprise' + 'NBPROFESSIONALFORCRM' = 'Microsoft Social Listening Professional' + 'INTUNE_O365' = 'Mobile Device Management for Office 365' + 'OFFICE_BUSINESS' = 'Office 365 Business' + 'OFFICESUBSCRIPTION' = 'Office 365 ProPlus' + 'OFFICESUBSCRIPTION_GOV' = 'Office 365 ProPlus for Government' + 'OFFICE_PRO_PLUS_SUBSCRIPTION_SMBIZ' = 'Office 365 Small Business Subscription' + 'SHAREPOINTWAC' = 'Office Online' + 'SHAREPOINTWAC_DEVELOPER' = 'Office Online Developer' + 'SHAREPOINTWAC_EDU' = 'Office Online EDU' + 'SHAREPOINTWAC_DEVELOPER_GOV' = 'Office Online for Government Developer' + 'SHAREPOINTWAC_GOV' = 'Office Online for Government' + 'ONEDRIVESTANDARD' = 'OneDrive for Business (Plan 1)' + 'ONEDRIVESTANDARD_GOV' = 'OneDrive for Business (Plan 1 for Government)' + 'ONEDRIVELITE' = 'OneDrive for Business Lite' + 'PARATURE_ENTERPRISE' = 'Parature Enterprise' + 'PARATURE_ENTERPRISE_GOV' = 'Parature Enterprise for Government' + 'BI_AZURE_P0' = 'Power BI' + 'PROJECT_ESSENTIALS' = 'Project Lite' + 'PROJECT_ESSENTIALS_GOV' = 'Project Lite for Government' + 'SHAREPOINT_PROJECT' = 'Project Online' + 'SHAREPOINT_PROJECT_EDU' = 'Project Online for Academics' + 'SHAREPOINT_PROJECT_GOV' = 'Project Online for Government' + 'PROJECT_CLIENT_SUBSCRIPTION' = 'Project Pro for Office 365' + 'PROJECT_CLIENT_SUBSCRIPTION_GOV' = 'Project Pro for Office 365 for Government' + 'SHAREPOINTSTANDARD' = 'SharePoint Online (Plan 1)' + 'SHAREPOINTSTANDARD_EDU' = 'SharePoint Online (Plan 1 for Academics)' + 'SHAREPOINTSTANDARD_GOV' = 'SharePoint Online (Plan 1 for Government)' + 'SHAREPOINTENTERPRISE' = 'SharePoint Online (Plan 2)' + 'SHAREPOINTENTERPRISE_EDU' = 'SharePoint Online (Plan 2 for Academics)' + 'SHAREPOINTENTERPRISE_GOV' = 'SharePoint Online (Plan 2 for Government)' + 'SHAREPOINT_S_DEVELOPER' = 'SharePoint Online for Developer' + 'SHAREPOINT_S_DEVELOPER_GOV' = 'SharePoint Online for Government Developer' + 'SHAREPOINTDESKLESS' = 'SharePoint Online Kiosk' + 'SHAREPOINTDESKLESS_GOV' = 'SharePoint Online Kiosk for Government' + 'VISIO_CLIENT_SUBSCRIPTION' = 'Visio Pro for Office 365' + 'VISIO_CLIENT_SUBSCRIPTION_GOV' = 'Visio Pro for Office 365 for Government' + 'YAMMER_ENTERPRISE' = 'Yammer Enterprise' + 'YAMMER_EDU' = 'Yammer for Academic For Academics' + 'FLOW_O365_P2' = 'Flow for Office 365 P2' + 'POWERAPPS_O365_P2' = 'PowerApps for Office 365 P2' + 'TEAMS1' = 'Microsoft Teams' + 'PROJECTWORKMANAGEMENT' = 'Microsoft Planner' + 'SWAY' = 'SWAY' + 'Deskless' = 'Microsoft StaffHub' + 'FLOW_O365_P3' = 'Flow for Office 365 P3' + 'POWERAPPS_O365_P3' = 'PowerApps for Office 365 P3' + 'ADALLOM_S_O365' = 'Office 365 Advanced Security Management' + 'EQUIVIO_ANALYTICS' = 'Office 365 Advanced eDiscovery' + 'LOCKBOX_ENTERPRISE' = 'Customer Lockbox' + 'EXCHANGE_ANALYTICS' = 'Microsoft MyAnalytics' + 'ATP_ENTERPRISE' = 'Exchange Online Advanced Threat Protection (These licenses do not need to be individually assigned)' + 'MCOEV' = 'Teams/Skype for Business Cloud PBX' + 'MCOMEETADV' = 'Teams/Skype for Business PSTN Conferencing' + } + } + + end + { + # Dump + $ServicePlanFriendlyList + } +} + +function Get-SkuPartNumberFriendlyNameList +{ + <# + .SYNOPSIS + A Hashtable of Office 365 SKUs and there Human understandable description + + .DESCRIPTION + Helper function to make the Office 365 SKUs as returned from scripts understandable for humans + + .EXAMPLE + PS C:\> Get-SkuPartNumberFriendlyNameList + + .NOTES + Internal Helper + + Version: 2.1 - Latest List + Author: Joerg Hochwald + License: The 3-Clause BSD License + #> + [CmdletBinding()] + [OutputType([hashtable])] + param () + + begin + { + # Cleanup + $SkuPartNumberFriendlyNameList = $null + } + + process + { + # Build the HashTable + $SkuPartNumberFriendlyNameList = @{ + 'AAD_BASIC' = 'Azure Active Directory Basic' + 'AAD_PREMIUM' = 'Azure Active Directory Premium' + 'RIGHTSMANAGEMENT' = 'Azure Active Directory Rights' + 'RIGHTSMANAGEMENT_FACULTY' = 'Azure Active Directory Rights for Faculty' + 'RIGHTSMANAGEMENT_GOV' = 'Azure Active Directory Rights for Government' + 'RIGHTSMANAGEMENT_STUDENT' = 'Azure Active Directory Rights for Students' + 'MFA_STANDALONE' = 'Azure Multi-Factor Authentication Premium Standalone' + 'EMS' = 'Microsoft Enterprise Mobility + Security Suite' + 'EXCHANGESTANDARD_FACULTY' = 'Exchange (Plan 1 for Faculty)' + 'EXCHANGESTANDARD_STUDENT' = 'Exchange (Plan 1 for Students)' + 'EXCHANGEENTERPRISE_FACULTY' = 'Exchange (Plan 2 for Faculty)' + 'EXCHANGEENTERPRISE_STUDENT' = 'Exchange (Plan 2 for Students)' + 'EXCHANGEARCHIVE' = 'Exchange Archiving' + 'EXCHANGEARCHIVE_FACULTY' = 'Exchange Archiving for Faculty' + 'EXCHANGEARCHIVE_GOV' = 'Exchange Archiving for Government' + 'EXCHANGEARCHIVE_STUDENT' = 'Exchange Archiving for Students' + 'EXCHANGESTANDARD_GOV' = 'Exchange for Government (Plan 1G)' + 'EXCHANGEENTERPRISE_GOV' = 'Exchange for Government (Plan 2G)' + 'EXCHANGEDESKLESS' = 'Exchange Kiosk' + 'EXCHANGEDESKLESS_GOV' = 'Exchange Kiosk for Government' + 'EXCHANGESTANDARD' = 'Exchange Plan 1' + 'EXCHANGEENTERPRISE' = 'Exchange Plan 2' + 'EOP_ENTERPRISE_FACULTY' = 'Exchange Protection for Faculty' + 'EOP_ENTERPRISE_GOV' = 'Exchange Protection for Government' + 'EOP_ENTERPRISE_STUDENT' = 'Exchange Protection for Student' + 'EXCHANGE_ONLINE_WITH_ONEDRIVE_LITE' = 'Exchange with OneDrive for Business' + 'INTUNE_A' = 'Intune' + 'MCOIMP_FACULTY' = 'Lync (Plan 1 for Faculty)' + 'MCOIMP_STUDENT' = 'Lync (Plan 1 for Students)' + 'MCOSTANDARD_FACULTY' = 'Lync (Plan 2 for Faculty)' + 'MCOSTANDARD_STUDENT' = 'Lync (Plan 2 for Students)' + 'MCOVOICECONF' = 'Lync (Plan 3)' + 'MCOIMP_GOV' = 'Lync for Government (Plan 1G)' + 'MCOSTANDARD_GOV' = 'Lync for Government (Plan 2G)' + 'MCOVOICECONF_GOV' = 'Lync for Government (Plan 3G)' + 'MCOINTERNAL' = 'Lync Internal Incubation and Corp to Cloud' + 'MCOIMP' = 'Skype Plan 1' + 'MCOSTANDARD' = 'Skype Plan 2' + 'MCOVOICECONF_FACULTY' = 'Lync Plan 3 for Faculty' + 'MCOVOICECONF_STUDENT' = 'Lync Plan 3 for Students' + 'CRMENTERPRISE' = 'Microsoft Dynamics CRM Online Enterprise' + 'CRMSTANDARD_GCC' = 'Microsoft Dynamics CRM Online Government Professional' + 'CRMSTANDARD' = 'Microsoft Dynamics CRM Online Professional' + 'DMENTERPRISE' = 'Microsoft Dynamics Marketing Online Enterprise' + 'INTUNE_O365_STANDALONE' = 'Mobile Device Management for Office 365' + 'OFFICE_BASIC' = 'Office 365 Basic' + 'O365_BUSINESS' = 'Office 365 Business' + 'O365_BUSINESS_ESSENTIALS' = 'Office 365 Business Essentials' + 'O365_BUSINESS_PREMIUM' = 'Office 365 Business Premium' + 'DEVELOPERPACK' = 'Office 365 Developer' + 'DEVELOPERPACK_GOV' = 'Office 365 Developer for Government' + 'EDUPACK_FACULTY' = 'Office 365 Education for Faculty' + 'EDUPACK_STUDENT' = 'Office 365 Education for Students' + 'EOP_ENTERPRISE' = 'Office 365 Exchange Protection Enterprise' + 'EOP_ENTERPRISE_PREMIUM' = 'Office 365 Exchange Protection Premium' + 'STANDARDPACK_GOV' = 'Office 365 for Government (Plan G1)' + 'STANDARDWOFFPACK_GOV' = 'Office 365 for Government (Plan G2)' + 'ENTERPRISEPACK_GOV' = 'Office 365 for Government (Plan G3)' + 'ENTERPRISEWITHSCAL_GOV' = 'Office 365 for Government (Plan G4)' + 'DESKLESSPACK_GOV' = 'Office 365 for Government (Plan F1G)' + 'STANDARDPACK_FACULTY' = 'Office 365 Plan A1 for Faculty' + 'STANDARDPACK_STUDENT' = 'Office 365 Plan A1 for Students' + 'STANDARDWOFFPACK_FACULTY' = 'Office 365 Plan A2 for Faculty' + 'STANDARDWOFFPACK_STUDENT' = 'Office 365 Plan A2 for Students' + 'ENTERPRISEPACK_FACULTY' = 'Office 365 Plan A3 for Faculty' + 'ENTERPRISEPACK_STUDENT' = 'Office 365 Plan A3 for Students' + 'ENTERPRISEWITHSCAL_FACULTY' = 'Office 365 Plan A4 for Faculty' + 'ENTERPRISEWITHSCAL_STUDENT' = 'Office 365 Plan A4 for Students' + 'STANDARDPACK' = 'Office 365 Plan E1' + 'STANDARDWOFFPACK' = 'Office 365 Plan E2' + 'ENTERPRISEPACK' = 'Office 365 Plan E3' + 'ENTERPRISEWITHSCAL' = 'Office 365 Plan E4' + 'DESKLESSPACK' = 'Office 365 Plan F1' + 'DESKLESSPACK_YAMMER' = 'Office 365 Plan F1 with Yammer' + 'OFFICESUBSCRIPTION' = 'Office Professional Plus' + 'OFFICESUBSCRIPTION_FACULTY' = 'Office Professional Plus for Faculty' + 'OFFICESUBSCRIPTION_GOV' = 'Office Professional Plus for Government' + 'OFFICESUBSCRIPTION_STUDENT' = 'Office Professional Plus for Students' + 'WACSHAREPOINTSTD_FACULTY' = 'Office Web Apps (Plan 1 For Faculty)' + 'WACSHAREPOINTSTD_STUDENT' = 'Office Web Apps (Plan 1 For Students)' + 'WACSHAREPOINTSTD_GOV' = 'Office Web Apps (Plan 1G for Government)' + 'WACSHAREPOINTENT_FACULTY' = 'Office Web Apps (Plan 2 For Faculty)' + 'WACSHAREPOINTENT_STUDENT' = 'Office Web Apps (Plan 2 For Students)' + 'WACSHAREPOINTENT_GOV' = 'Office Web Apps (Plan 2G for Government)' + 'WACSHAREPOINTSTD' = 'Office Web Apps with SharePoint Plan 1' + 'WACSHAREPOINTENT' = 'Office Web Apps with SharePoint Plan 2' + 'ONEDRIVESTANDARD' = 'OneDrive for Business' + 'ONEDRIVESTANDARD_GOV' = 'OneDrive for Business for Government (Plan 1G)' + 'WACONEDRIVESTANDARD' = 'OneDrive for Business with Office Web Apps' + 'WACONEDRIVESTANDARD_GOV' = 'OneDrive for Business with Office Web Apps for Government' + 'PARATURE_ENTERPRISE' = 'Parature Enterprise' + 'PARATURE_ENTERPRISE_GOV' = 'Parature Enterprise for Government' + 'POWER_BI_STANDARD' = 'Power BI' + 'POWER_BI_STANDALONE' = 'Power BI for Office 365' + 'POWER_BI_STANDALONE_FACULTY' = 'Power BI for Office 365 for Faculty' + 'POWER_BI_STANDALONE_STUDENT' = 'Power BI for Office 365 for Students' + 'PROJECTESSENTIALS' = 'Project Essentials' + 'PROJECTESSENTIALS_GOV' = 'Project Essentials for Government' + 'PROJECTONLINE_PLAN_1' = 'Project Plan 1' + 'PROJECTONLINE_PLAN_1_FACULTY' = 'Project Plan 1 for Faculty' + 'PROJECTONLINE_PLAN_1_GOV' = 'Project Plan 1for Government' + 'PROJECTONLINE_PLAN_1_STUDENT' = 'Project Plan 1 for Students' + 'PROJECTONLINE_PLAN_2' = 'Project Plan 2' + 'PROJECTONLINE_PLAN_2_FACULTY' = 'Project Plan 2 for Faculty' + 'PROJECTONLINE_PLAN_2_GOV' = 'Project Plan 2 for Government' + 'PROJECTONLINE_PLAN_2_STUDENT' = 'Project Plan 2 for Students' + 'PROJECTCLIENT' = 'Project Pro for Office 365' + 'PROJECTCLIENT_FACULTY' = 'Project Pro for Office 365 for Faculty' + 'PROJECTCLIENT_GOV' = 'Project Pro for Office 365 for Government' + 'PROJECTCLIENT_STUDENT' = 'Project Pro for Office 365 for Students' + 'SHAREPOINTSTANDARD_FACULTY' = 'SharePoint (Plan 1 for Faculty)' + 'SHAREPOINTSTANDARD_STUDENT' = 'SharePoint (Plan 1 for Students)' + 'SHAREPOINTSTANDARD_YAMMER' = 'SharePoint (Plan 1 with Yammer)' + 'SHAREPOINTENTERPRISE_FACULTY' = 'SharePoint (Plan 2 for Faculty)' + 'SHAREPOINTENTERPRISE_STUDENT' = 'SharePoint (Plan 2 for Students)' + 'SHAREPOINTENTERPRISE_YAMMER' = 'SharePoint (Plan 2 with Yammer)' + 'SHAREPOINTSTANDARD_GOV' = 'SharePoint for Government (Plan 1G)' + 'SHAREPOINTENTERPRISE_GOV' = 'SharePoint for Government (Plan 2G)' + 'SHAREPOINTDESKLESS' = 'SharePoint Kiosk' + 'SHAREPOINTSTANDARD' = 'SharePoint Plan 1' + 'SHAREPOINTENTERPRISE' = 'SharePoint Plan 2' + 'SMB_BUSINESS' = 'SMB Business' + 'SMB_BUSINESS_ESSENTIALS' = 'SMB Business Essentials' + 'SMB_BUSINESS_PREMIUM' = 'SMB Business Premium' + 'VISIOCLIENT' = 'Visio Pro for Office 365' + 'VISIOCLIENT_FACULTY' = 'Visio Pro for Office 365 for Faculty' + 'VISIOCLIENT_GOV' = 'Visio Pro for Office 365 for Government' + 'VISIOCLIENT_STUDENT' = 'Visio Pro for Office 365 for Students' + 'YAMMER_ENTERPRISE_STANDALONE' = 'Yammer Enterprise Standalone' + 'RIGHTSMANAGEMENT_ADHOC' = 'Azure Rights Management Service' + 'ENTERPRISEPREMIUM' = 'Office 365 Enterprise E5' + } + } + + end + { + # Dump + $SkuPartNumberFriendlyNameList + } +} +#endregion HelperFunctions + +# region MainFunctions +function Convert-MsolServicePlanName +{ + <# + .SYNOPSIS + Convert between the Office 365 ServicePlanName from Get-MsolAccountSku to a human understandable format. It works in both directions + + .DESCRIPTION + Coverts the Office 365 ServicePlanName from Get-MsolAccountSku to a human understandable format (as viewed in the Office 365 Admin Portal). + I use this for reporting and other licence related scripts to make the output understandable for the user. + + .PARAMETER ServicePlanName + ServicePlanName from PowerShell query, e.g. Intune + + .PARAMETER ServicePlanFriendlyName + Human underandable description of a plan, e.g. Azure Multi-Factor Authentication + + .EXAMPLE + # Get all availible Services in a Human understanable Format + PS> Get-MsolAccountSku | Select-Object -Property @{ + Name = 'ServicePlanName' + Expression = { + $_.ServiceStatus.ServicePlan.ServiceName + } + } | ForEach-Object -Process { + $_.ServicePlanName + } | Convert-MsolServicePlanName + + Teams/Skype for Business Cloud PBX + Power BI + Teams/Skype for Business PSTN Conferencing + Microsoft StaffHub + Microsoft Teams + Office Online + Microsoft Planner + SWAY + Mobile Device Management for Office 365 + Yammer Enterprise + Skype for Business Online (Plan 2) + SharePoint Online (Plan 1) + Exchange Online (Plan 1) + + .EXAMPLE + # Convert a SKU Service Name to a human understandable format + PS> Convert-MsolServicePlanName -ServicePlanName "AAD_BASIC" + + Azure Active Directory Basic + + .EXAMPLE + # Convert a human understandable format to SKU Service Name, to use in scripts + PS> Convert-MsolServicePlanName -ServicePlanFriendlyName "Azure Multi-Factor Authentication" + + MFA_PREMIUM + + .NOTES + Version: 2.1 - Latest List + Author: Joerg Hochwald + License: The 3-Clause BSD License + #> + [CmdletBinding(DefaultParameterSetName = 'ByFriendlyName')] + param + ( + [Parameter(ParameterSetName = 'ByServicePlanName', + Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 0, + HelpMessage = 'ServicePlanName from PowerShell query, e.g. AAD_BASIC')] + [Alias('Name')] + [string] + $ServicePlanName, + [Parameter(ParameterSetName = 'ByFriendlyName', + Mandatory = $true, + Position = 0, + HelpMessage = 'Friendly name of a plan, e.g. Exchange Online (Plan 1)')] + [Alias('FriendlyName')] + [string] + $ServicePlanFriendlyName + ) + + process + { + # Moved to a dedicated function + $ServicePlanFriendlyList = (Get-ServicePlanFriendlyList) + + if ($ServicePlanName) + { + $ServicePlanFriendlyList["$ServicePlanName"] + } + + if ($ServicePlanFriendlyName) + { + ($ServicePlanFriendlyList.GetEnumerator() | Where-Object -FilterScript { + $_.Value -eq "$ServicePlanFriendlyName" + }).Name + } + } +} + +function Convert-MsolAccountSkuName +{ + <# + .SYNOPSIS + Convert between the Office 365 SKU Name from Get-MsolAccountSku to a human understandable format. It works in both directions + + .DESCRIPTION + Coverts the Office 365 SKU Name from Get-MsolAccountSku to a human understandable format (as viewed in the Office 365 Admin Portal). + I use this for reporting and other licence related scripts to make the output understandable for the user. + + .PARAMETER SkuPartNumber + ServicePlanName from scripted query, e.g. EXCHANGEENTERPRISE + + .PARAMETER SkuPartNumberFriendlyName + human understandable format of a plan, e.g. Exchange Plan 1 + + .EXAMPLE + # Get a human understandable output for all existing SKUs + Get-MsolAccountSku | Select-Object -ExpandProperty SkuPartNumber | Convert-MsolAccountSkuName + + Power BI + Office 365 Plan E1 + + .EXAMPLE + # Get the human understandable description from a SKU Number/Name + Convert-MsolAccountSkuName -SkuPartNumber 'EXCHANGEENTERPRISE' + + Exchange Plan 2 + + .EXAMPLE + # Get the script compatible description from an human understandable format + Convert-MsolAccountSkuName -SkuPartNumberFriendlyName 'Exchange Plan 1' + + EXCHANGESTANDARD + + .NOTES + Version: 2.1 - Latest List + Author: Joerg Hochwald + License: The 3-Clause BSD License + #> + [CmdletBinding(DefaultParameterSetName = 'BySkuFriendlyName')] + param + ( + [Parameter(ParameterSetName = 'BySkuPartNumber', + Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true, + Position = 0, + HelpMessage = 'ServicePlanName from PowerShell query, e.g. "EXCHANGEENTERPRISE"')] + [Alias('PartNumber')] + [string] + $SkuPartNumber, + [Parameter(ParameterSetName = 'BySkuFriendlyName', + Mandatory = $true, + Position = 0, + HelpMessage = 'Friendly name of a plan, e.g. "Exchange Plan 1"')] + [Alias('FriendlyName')] + [string] + $SkuPartNumberFriendlyName + ) + + process + { + # Moved to a dedicated function + $SkuPartNumberFriendlyNameList = (Get-SkuPartNumberFriendlyNameList) + + if ($SkuPartNumber) + { + $SkuPartNumberFriendlyNameList["$SkuPartNumber"] + } + + if ($SkuPartNumberFriendlyName) + { + ($SkuPartNumberFriendlyNameList.GetEnumerator() | Where-Object -FilterScript { + $_.Value -eq "$SkuPartNumberFriendlyName" + }).Name + } + } +} +#endregion MainFunctions + +#region Info +Write-Output -InputObject 'MsolServicePlanName:' +Get-MsolAccountSku | Select-Object -Property @{ + Name = 'ServicePlanName' + Expression = { + $_.ServiceStatus.ServicePlan.ServiceName + } +} | ForEach-Object -Process { + $_.ServicePlanName +} | Convert-MsolServicePlanName + +Write-Output -InputObject '' + +Write-Output -InputObject 'MsolAccountSkuName:' +Get-MsolAccountSku | Select-Object -ExpandProperty SkuPartNumber | Convert-MsolAccountSkuName +#endregion Info + + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Find-AdminAssignedLicenses.ps1 b/Powershell/PowerShell-collection/Office365/Find-AdminAssignedLicenses.ps1 new file mode 100644 index 0000000..da0be07 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Find-AdminAssignedLicenses.ps1 @@ -0,0 +1,262 @@ +#requires -Version 3.0 -Modules MSOnline +<# + .SYNOPSIS + Find all direct assigned Microsoft 365 licenses + + .DESCRIPTION + Find all direct assigned Microsoft 365 licenses. + you can display the licenses or export the info to a CSV file + + .PARAMETER Export + Export the information to CSV. + + .PARAMETER Display + Use Out-GridView to display the information. + + .PARAMETER Path + Path to the CSV + + .PARAMETER MsolName + The MSOL short name. + e.g. contoso + + .EXAMPLE + PS C:\> .\Find-AdminAssignedLicenses.ps1 -MsolName 'contoso' -Display + + Find all direct assigned Microsoft 365 licenses and show it via Out-GridView + + .EXAMPLE + PS C:\> .\Find-AdminAssignedLicenses.ps1 -MsolName 'contoso' -Export + + Find all direct assigned Microsoft 365 licenses and export it to the default CSV + + .EXAMPLE + PS C:\> .\Find-AdminAssignedLicenses.ps1 -MsolName 'contoso' -Export -Path 'C:\scripts\PowerShell\export\AdminAssignedLicenses.csv' + + Find all direct assigned Microsoft 365 licenses and export it to a given CSV + + .NOTES + The next version will bring another switch to dump the info to the console. Based on a request of a customer. + + This script based on the idea of Joachim of powershell24.de - It replaced my old crappy self developed approach. + + .LINK + https://powershell24.de/en/2020/08/25/direkt-zugewiesene-plane-auslesen/ +#> +[CmdletBinding(DefaultParameterSetName = 'Display', + ConfirmImpact = 'None')] +param +( + [Parameter(ParameterSetName = 'Export', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('ExportInfo', 'ExportCSV')] + [switch] + $Export, + [Parameter(ParameterSetName = 'Display', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('OutGridView', 'GridView', 'Info')] + [switch] + $Display, + [Parameter(ParameterSetName = 'Export', + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('CSVPath', 'CSVFile')] + [string] + $Path = '.\M365_admin_assignes_licenses.csv', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('MsolShortName')] + [string] + $MsolName = 'contoso' +) + +begin +{ + #region RunVerbose + if ($PSCmdlet.MyInvocation.BoundParameters['Verbose'].IsPresent) + { + $RunVerbose = $true + } + else + { + $RunVerbose = $false + } + #endregion RunVerbose + + #region DryRun + if ($PSCmdlet.MyInvocation.BoundParameters['Whatif'].IsPresent) + { + $IsDryRun = $true + } + else + { + $IsDryRun = $false + } + #endregion DryRun + + #region GetUserInfo + $paramGetMsolUser = @{ + All = $true + ErrorAction = 'Stop' + Verbose = $RunVerbose + } + $AllUsers = (Get-MsolUser @paramGetMsolUser) + + # Filter the licensed users + $AllUsers = ($AllUsers | Where-Object { + $_.isLicensed -eq $true + }) + #endregion GetUserInfo + + #region CreateObjects + $paramNewObject = @{ + TypeName = 'System.Collections.Generic.List[System.Object]' + Verbose = $RunVerbose + } + $DirectAssignments = (New-Object @paramNewObject) + $SkuFilter = (New-Object @paramNewObject) + $FilterSku = (New-Object @paramNewObject) + #endregion CreateObjects + + #region LicenseFilters + [String[]]$FilterSku = @( + 'POWER_BI_STANDARD' + 'POWERAPPS_VIRAL' + 'POWERAPPS_INDIVIDUAL_USER' + 'FLOW_FREE' + 'MCOMEETADV' + 'PROJECTPROFESSIONAL' + ) + #endregion LicenseFilters + + #region FilterSku + foreach ($SkuFilterItem in $FilterSku) + { + $SkuFilterSingleItem = $null + $SkuFilterSingleItem = ($MsolName + ':' + $SkuFilterItem) + $SkuFilter.Add($SkuFilterSingleItem) + } + #endregion FilterSku +} + +process +{ + #region UserLoop + foreach ($User in $AllUsers) + { + # Be verbose + Write-Verbose -Message ('Gathering information for {0}' -f $User.UserPrincipalName) + + # Store the object information + $UserObjectID = ($User.ObjectId) + $AllUserLicenses = ($User.Licenses) + + #region LicenseLoop + foreach ($License in $AllUserLicenses) + { + # Store the object information + $Assignments = ($License.GroupsAssigningLicense) + + #region IsLicenseAssigned + if ($License.GroupsAssigningLicense.Count -eq 0) + { + Write-Verbose -Message 'No direct assigned licenses found.' + } + else + { + # OK, now loop over the assigned licenses + foreach ($Assignment in $Assignments) + { + # Is it assigned to the user? + if ($Assignment -ieq $UserObjectID) + { + # Apply the Filter + if ($SkuFilter -match $License.AccountSkuId) + { + Write-Verbose -Message ('The License {0} was filtered.' -f $License.AccountSkuId) + } + else + { + # OK, we found something + $DirectAssignment = ('' | Select-Object -Property UserPrincipalName, AccountSkuId -Verbose:$RunVerbose) + $DirectAssignment.UserPrincipalName = ($User.UserPrincipalName) + $DirectAssignment.AccountSkuId = ($License.AccountSkuId.Replace(($MsolName + ':'), '')) + + # Add to the list + $DirectAssignments.Add($DirectAssignment) + } + + # Done + break + } + } + } + #endregion IsLicenseAssigned + } + #endregion LicenseLoop + } + #endregion UserLoop +} + +end +{ + #region SwitchHandler + switch ($PSCmdlet.ParameterSetName) + { + 'Display' + { + # OK, dump the info + ($DirectAssignments | Out-GridView -PassThru -Verbose:$RunVerbose) + } + 'Export' + { + # export logic + $paramExportCsv = @{ + Path = $Path + Force = $true + Encoding = 'UTF8' + NoTypeInformation = $true + Delimiter = ';' + Confirm = $false + Verbose = $RunVerbose + WhatIf = $IsDryRun + ErrorAction = 'Continue' + } + $null = ($DirectAssignments | Export-Csv @paramExportCsv) + } + } + #endregion SwitchHandler +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/FixPersonalSPOSite.ps1 b/Powershell/PowerShell-collection/Office365/FixPersonalSPOSite.ps1 new file mode 100644 index 0000000..61629d6 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/FixPersonalSPOSite.ps1 @@ -0,0 +1,151 @@ +#requires -Version 3.0 -Modules AzureAD, Microsoft.Online.SharePoint.PowerShell +<# + .SYNOPSIS + Provision new Users personal SharePoint site + + .DESCRIPTION + Provision new Users personal SharePoint site, Will also trigger the OneDrive provisioning. + + .PARAMETER TenantName + Microsoft 365 Tenant name (e.g. contoso for contoso.onmicrosoft.com) + Do not use any of the vanity domains of your tenant here! + + .EXAMPLE + PS C:\> .\FixPersonalSPOSite.ps1 + Provision new Users personal SharePoint site + + .EXAMPLE + PS C:\> .\FixPersonalSPOSite.ps1 -TenantName 'contoso' + Provision new Users personal SharePoint site for the Microsoft 365 tenant with the name 'contoso' (for contoso.onmicrosoft.com) + + .NOTES + I had issues where newly created users where unable to access there personal site/OneDrive via portal.office.com + We found this issue in at least two different tenants, therefore we decided to figure out a workaround. + + Want to know how the magic workaround works? + See the last command of this script, Get-SPOSite does all the magic. Don't ask! + + Author: Joerg Hochwald - https://hochwald.net + Contributor: Christopher Pope - https://hope-this-helps.de +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [Alias('Tenant')] + [string] + $TenantName = ' contoso' +) + +begin +{ + # Set the URL main part + $AdminUrl = ('https://' + $TenantName + '-admin.sharepoint.com') + + # Connect to AzureAD + Connect-AzureAD -ErrorAction Stop + + # Connect to SharePoint Online + Connect-SPOService -Url $AdminUrl -ErrorAction Stop +} + +process +{ + # Get all User from the AzureAD + # Mind the Gap: -All is not a switch, it IS a Boolean <- WTF? + $paramGetAzureADUser = @{ + All = $true + ErrorAction = 'SilentlyContinue' + } + $NewODFBUsers = (Get-AzureADUser @paramGetAzureADUser | Select-Object) + + # Filter licensed users + $NewODFBUsers = ($NewODFBUsers | Where-Object -FilterScript { + <# + You can Filter much more, if you like + We Filter: + 1. User with an assigned License + 2. All external users (based on the '#EXT#' in the UserPrincipalName) + 3. All users without a vanity domain (e.g. everyone within @NAME.onmicrosoft.com) <- Review this before using it!!! + #> + (($_.AssignedLicenses -ne $null) -and ($_.UserPrincipalName -notlike ('*#EXT#@*')) -and ($_.UserPrincipalName -notlike ('*@' + $TenantName + '.onmicrosoft.com'))) + } | Select-Object -ExpandProperty UserPrincipalName -ErrorAction SilentlyContinue) + + # The Limit of Request-SPOPersonalSite is 200 + $SliceSize = 150 + + # Create a new Index + $SliceIndex = 0 + + # Slice the big array into smaller chunks + while ($($SliceSize * $SliceIndex) -lt $NewODFBUsers.Length) + { + # Cleanup + $NewODFBUsersSlice = $null + + # Put the number of peaces into the new chunk (e.g. the new object) + $NewODFBUsersSlice = ($NewODFBUsers | Select-Object -First $SliceSize -Skip ($SliceSize * $SliceIndex) -ErrorAction SilentlyContinue) + + # Just fire the Request, the hard limit is 200 per call + $paramRequestSPOPersonalSite = @{ + UserEmails = $NewODFBUsersSlice + NoWait = $true + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + } + $null = (Request-SPOPersonalSite @paramRequestSPOPersonalSite) + + # Count the slice + $SliceIndex++ + } + + # Cool down and let Azure (SPO in this case) do the provisioning job in the background + Start-Sleep -Seconds 60 + + <# + Reference is Case #:23027858 (One Drive is not accessible via portal.office.com) + Solution: This get will do the magic! You have to do a Select on the "Owner" object to make the magic work. + Looks like the get will trigger something in the background! + #> + $paramGetSPOSite = @{ + IncludePersonalSite = $true + Limit = 'all' + Filter = "Url -like '-my.sharepoint.com/personal/'" + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + } + $null = (Get-SPOSite @paramGetSPOSite | Select-Object -Property Url, Owner) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Get-MFAUserReport.ps1 b/Powershell/PowerShell-collection/Office365/Get-MFAUserReport.ps1 new file mode 100644 index 0000000..345a9b0 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Get-MFAUserReport.ps1 @@ -0,0 +1,200 @@ +function Get-MFAUserReport +{ + <# + .SYNOPSIS + Get a Azure AD MFA User report + + .DESCRIPTION + Get a Azure AD MFA User report, the function can export the report as CSV. + The export is disabled by default. + + .PARAMETER Export + Export the MFA Report to CSV? + + .PARAMETER Path + Path of the MFA Export CSV + + .EXAMPLE + PS> Get-MFAUserReport + + Get a Azure AD MFA User report + + .EXAMPLE + PS> Get-MFAUserReport -Export + + Get a Azure AD MFA User report and export it to the default report (C:\scripts\PowerShell\exports\MFAUsers.csv) + + .EXAMPLE + PS> Get-MFAUserReport -Export -Path 'C:\scripts\PowerShell\exports\AllMFAUsers.csv' + + Get a Azure AD MFA User report and export it to given report (C:\scripts\PowerShell\exports\AllMFAUsers.csv) + + .NOTES + ParameterSet added + + License: BSD 3-Clause + #> + [CmdletBinding(DefaultParameterSetName = 'Normal', + SupportsShouldProcess)] + param + ( + [Parameter(ParameterSetName = 'Export', + ValueFromPipeline, + Position = 1)] + [Alias('CSV')] + [switch] + $Export, + [Parameter(ParameterSetName = 'Export', + ValueFromPipeline, + Position = 2)] + [string] + $Path = 'C:\scripts\PowerShell\exports\MFAUsers.csv' + ) + + begin + { + # Defaults + $CNT = 'Continue' + $STP = 'Stop' + + # Cleanup + $Report = @() + $i = 0 + + if ($pscmdlet.ShouldProcess('MFA Users', 'Get')) + { + # get all Accounts + try + { + $Accounts = (Get-MsolUser -All -ErrorAction $STP -WarningAction $CNT | Where-Object -FilterScript { + $_.StrongAuthenticationMethods -ne $Null + } | Sort-Object -Property DisplayName) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + } + } + + process + { + if ($pscmdlet.ShouldProcess('MFA Users', 'Process')) + { + foreach ($Account in $Accounts) + { + $AccountDisplayName = $Account.DisplayName + Write-Verbose -Message ('Processing {0}' -f $AccountDisplayName) + + # Counter + $i++ + + # Select Methods + $Methods = ($Account | Select-Object -ExpandProperty StrongAuthenticationMethods) + $MFA = ($Account | Select-Object -ExpandProperty StrongAuthenticationUserDetails) + $State = ($Account | Select-Object -ExpandProperty StrongAuthenticationRequirements) + + $Methods | ForEach-Object -Process { + if ($_.IsDefault -eq $true) + { + $Method = $_.MethodType + } + } + + if ($State.State) + { + $MFAStatus = $State.State + } + else + { + $MFAStatus = 'Disabled' + } + + $Object = [PSCustomObject][Ordered]@{ + User = $Account.DisplayName + UPN = $Account.UserPrincipalName + MFAMethod = $Method + MFAPhone = $MFA.PhoneNumber + MFAEmail = $MFA.Email + MFAStatus = $MFAStatus + } + + # Add Obejct to report + $Report += $Object + } + } + } + + end + { + if ($pscmdlet.ShouldProcess('MFA Users', 'Report')) + { + Write-Verbose -Message ('{0} accounts are MFA-enabled' -f $i) + + if ($pscmdlet.ParameterSetName -eq 'Export') + { + try + { + $Null = ($Report | Export-Csv -NoTypeInformation -Path $Path -Force -ErrorAction $STP -WarningAction $CNT) + } + catch + { + $line = ($_.InvocationInfo.ScriptLineNumber) + + # Dump the Info + Write-Warning -Message ('Error was in Line {0}' -f $line) + + # Dump the Error catched + Write-Error -Message $_ -ErrorAction $STP + + # Something that should never be reached + break + } + } + else + { + # Dump to console + $Report + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Get-MicrosoftCloudTenantInfo.ps1 b/Powershell/PowerShell-collection/Office365/Get-MicrosoftCloudTenantInfo.ps1 new file mode 100644 index 0000000..a0a79e8 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Get-MicrosoftCloudTenantInfo.ps1 @@ -0,0 +1,179 @@ +function Get-MicrosoftCloudTenantInfo +{ + <# + .SYNOPSIS + Check if a given Name is available as Office365/Azure Tenant Name + + .DESCRIPTION + Check if a given Name is available as Office365/Azure Tenant Name and optional return the Tenant ID if the Tenant exists. + + .PARAMETER name + Check if a given Name is available as Office365/Azure Tenant Name + + .PARAMETER id + Get the Tenant ID + + .EXAMPLE + PS C:\> Get-MicrosoftCloudTenantInfo -name 'Contoso' -id + The Tenant ID of contoso.onmicrosoft.com (contoso) is XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX + + .EXAMPLE + PS C:\> Get-MicrosoftCloudTenantInfo -name 'Contoso' + The Tenant contoso.onmicrosoft.com (contoso) is available + + .EXAMPLE + PS C:\> Get-MicrosoftCloudTenantInfo -name 'Contoso' + WARNING: The Tenant contoso.onmicrosoft.com (contoso) is taken! + + .NOTES + Changelog: Initial Public Release + #> + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + Position = 1, + HelpMessage = 'Check if a given Name is availible as Office365/Azure Tenant Name')] + [ValidateNotNullOrEmpty()] + [string] + $name, + [Alias('TenantID')] + [switch] + $id + ) + + begin + { + # Define some defaults + $ST = 'Stop' + $SC = 'SilentlyContinue' + + # Do not use SSLv3 for any kind of Web Requests + if ([Net.ServicePointManager]::SecurityProtocol -notmatch 'TLS12') + { + [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::TLS11 + [Net.ServicePointManager]::SecurityProtocol += [Net.SecurityProtocolType]::TLS12 + } + + # Cleanup + $available = $null + $TenantID = $null + $TenantLongName = $null + + # Make the tenant name lowercase all the way, just in case! + $name = $name.ToLower() + + # Where to check + $uri = 'https://portal.office.com/Signup/CheckDomainAvailability.ajax' + + # OK, the Body looks creapy + $body = 'p0=' + $name + '&assembly=BOX.Admin.UI%2C+Version%3D16.0.0.0%2C+Culture%3Dneutral%2C+PublicKeyToken%3Dnull&class=Microsoft.Online.BOX.Signup.UI.SignupServerCalls' + } + + process + { + # get the Info via Rest + $paramInvokeRestMethod = $null + $paramInvokeRestMethod = @{ + Method = 'Post' + Uri = $uri + Body = $body + ErrorAction = $SC + WarningAction = $SC + } + $response = (Invoke-RestMethod @paramInvokeRestMethod) + + # Error handler + $valid = $response.Contains('SessionValid') + + if ($valid -eq $false) + { + # Whoops + Write-Error -Message $response -ErrorAction $ST + exit + } + + # Looks good + $available = $response.Contains('') + } + + end + { + # Internal log Name + $TenantLongName = $name + '.onmicrosoft.com' + + if ($available) + { + Write-Output -InputObject ('The Tenant {0} ({1}) is available' -f $TenantLongName, $name) + } + else + { + if ($id) + { + # Cleanup + $TenantID = $null + + try + { + # Build the UIR + $TenantIDURI = 'https://login.windows.net/' + $name + '.onmicrosoft.com/.well-known/openid-configuration' + + # Get the Info via regular call and split it + $paramInvokeWebRequest = $null + $paramInvokeWebRequest = @{ + Uri = $TenantIDURI + ErrorAction = $ST + } + + $TenantID = ((Invoke-WebRequest @paramInvokeWebRequest | ConvertFrom-Json -ErrorAction $ST).token_endpoint.Split('/')[3]) + + Write-Output -InputObject ('The Tenant ID of {0} ({1}) is {2}' -f $TenantLongName, $name, $TenantID) + } + catch + { + # Whoops + Write-Warning -Message 'The Tenant is taken, but we where unable to get the Tenant ID!!!' + } + } + else + { + Write-Warning -Message ('The Tenant {0} ({1}) is taken!' -f $TenantLongName, $name) + } + } + + # Cleanup + $available = $null + $TenantID = $null + $TenantLongName = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Get-MicrosoftWhiteboardReport.ps1 b/Powershell/PowerShell-collection/Office365/Get-MicrosoftWhiteboardReport.ps1 new file mode 100644 index 0000000..55b325f --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Get-MicrosoftWhiteboardReport.ps1 @@ -0,0 +1,307 @@ +#requires -Version 3.0 -Modules AzureAD, WhiteboardAdmin +function Get-MicrosoftWhiteboardReport +{ + <# + .SYNOPSIS + Get all Whiteboards for a given user + + .DESCRIPTION + Get all Whiteboards for a given UserID or UserPrincipalName + + .PARAMETER UserId + The UserID (AzureAD Object ID) for the User + + .PARAMETER UserName + The UserPrincipalName for the User + + .EXAMPLE + PS C:\> Get-MicrosoftWhiteboardReport -UserId '43c67825-9835-48c8-9a85-6ecf681bf5c9' + + Get all Whiteboards for the User with the Azure AD Object ID '43c67825-9835-48c8-9a85-6ecf681bf5c9' + + .EXAMPLE + PS C:\> Get-MicrosoftWhiteboardReport -UserName 'john.doe@contoso.com' + + Get all Whiteboards for the User 'john.doe@contoso.com' + + .EXAMPLE + PS C:\> Get-MicrosoftWhiteboardReport -UserName 'john.doe@contoso.com' | Where-Object {$_.Id -eq '01b3d6ee-edbb-456a-8805-f768aaedcc6a'} + + Get the infomation about the Whiteboard with the ID '01b3d6ee-edbb-456a-8805-f768aaedcc6a' ot hte user 'john.doe@contoso.com' + + .OUTPUTS + psobject + + .NOTES + Hard to automate: The WhiteboardAdmin does not have a connect function and will always prompt for auth (and then cache the credentials used to connect). + + .LINK + Get-Whiteboard + + .LINK + https://www.powershellgallery.com/packages/WhiteboardAdmin/ + #> + [CmdletBinding(DefaultParameterSetName = 'UseID', + ConfirmImpact = 'None')] + [OutputType([psobject], ParameterSetName = 'UseID')] + [OutputType([psobject], ParameterSetName = 'UseName')] + [OutputType([psobject])] + param + ( + [Parameter(ParameterSetName = 'UseID', HelpMessage = 'The UserID (AzureAD Obejct ID) for the User', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('ObejctID')] + [string] + $UserId, + [Parameter(ParameterSetName = 'UseName', HelpMessage = 'The UserPrincipalName for the User', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('UserPrincipalName')] + [string] + $UserName + ) + + begin + { + try + { + try + { + $null = (Get-AzureADTenantDetail -ErrorAction Stop) + } + catch + { + Connect-AzureAD + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + + if ($PsCmdlet.ParameterSetName -eq 'UseName') + { + $UserId = (Get-AzureADUser -Filter ("userPrincipalName eq '{0}'" -f $UserName) | Select-Object -ExpandProperty ObjectId) + } + + $UserWhiteboards = $null + $UserWhiteboards = (Get-Whiteboard -UserId $UserId -ErrorAction SilentlyContinue | Select-Object -Property *) + } + + process + { + if ($UserWhiteboards) + { + # Create a new object for the report + $Report = @() + + # Loop over the existing Whiteboards + foreach ($UserWhiteboard in $UserWhiteboards) + { + try + { + $objUserId = (Get-AzureADUser -ObjectId $UserWhiteboard.userId -ErrorAction SilentlyContinue | Select-Object -ExpandProperty DisplayName) + + if (-not ($objUserId)) + { + $objUserId = $UserWhiteboard.userId + } + + $objCreatedBy = (Get-AzureADUser -ObjectId $UserWhiteboard.createdBy -ErrorAction SilentlyContinue | Select-Object -ExpandProperty DisplayName) + + if (-not ($objCreatedBy)) + { + $objCreatedBy = $UserWhiteboard.createdBy + } + + $objOwnerId = (Get-AzureADUser -ObjectId $UserWhiteboard.ownerId -ErrorAction SilentlyContinue | Select-Object -ExpandProperty DisplayName) + + if (-not ($objOwnerId)) + { + $objOwnerId = $UserWhiteboard.ownerId + } + + $ObjOwnerTenantId = (Get-AzureADTenantDetail) + + if ($ObjOwnerTenantId.ObjectId -eq $UserWhiteboard.ownerTenantId) + { + $ObjOwnerTenantId = $ObjOwnerTenantId.DisplayName + } + else + { + $ObjOwnerTenantId = ('unknown (' + $UserWhiteboard.ownerTenantId + ')') + } + + # Transform the DateTime String + $objCreated = ($UserWhiteboard.createdTime | Get-Date -Format 'yyyy-MM-dd HH:mm' -ErrorAction SilentlyContinue) + $objInvited = ($UserWhiteboard.invitedTime | Get-Date -Format 'yyyy-MM-dd HH:mm' -ErrorAction SilentlyContinue) + $objPersonalLastModified = ($UserWhiteboard.personalLastModifiedTime | Get-Date -Format 'yyyy-MM-dd HH:mm' -ErrorAction SilentlyContinue) + $objLastModified = ($UserWhiteboard.lastModifiedTime | Get-Date -Format 'yyyy-MM-dd HH:mm' -ErrorAction SilentlyContinue) + $objGlobalLastViewed = ($UserWhiteboard.globalLastViewedTime | Get-Date -Format 'yyyy-MM-dd HH:mm' -ErrorAction SilentlyContinue) + $objLastViewed = ($UserWhiteboard.lastViewedTime | Get-Date -Format 'yyyy-MM-dd HH:mm' -ErrorAction SilentlyContinue) + + $obj = New-Object -TypeName psobject + $obj | Add-Member -MemberType NoteProperty -Name Title -Value $UserWhiteboard.title + $obj | Add-Member -MemberType NoteProperty -Name Id -Value $UserWhiteboard.id + + $obj | Add-Member -MemberType NoteProperty -Name UserId -Value $objUserId + $objUserId = $null + + $obj | Add-Member -MemberType NoteProperty -Name CreatedBy -Value $objCreatedBy + $objCreatedBy = $null + + $obj | Add-Member -MemberType NoteProperty -Name OwnerId -Value $objOwnerId + $objOwnerId = $null + + $obj | Add-Member -MemberType NoteProperty -Name OwnerTenant -Value $ObjOwnerTenantId + $ObjOwnerTenantId = $null + + $obj | Add-Member -MemberType NoteProperty -Name IsShared -Value $UserWhiteboard.isShared + + if ($objCreated) + { + $obj | Add-Member -MemberType NoteProperty -Name Created -Value $objCreated + $objCreated = $null + } + + if ($objInvited) + { + $obj | Add-Member -MemberType NoteProperty -Name Invited -Value $objInvited + $objInvited = $null + } + + if ($objPersonalLastModified) + { + $obj | Add-Member -MemberType NoteProperty -Name PersonalLastModified -Value $objPersonalLastModified + $objPersonalLastModified = $null + } + + if ($objLastModified) + { + $obj | Add-Member -MemberType NoteProperty -Name LastModified -Value $objLastModified + $objLastModified = $null + } + + if ($objGlobalLastViewed) + { + $obj | Add-Member -MemberType NoteProperty -Name GlobalLastViewed -Value $objGlobalLastViewed + $objGlobalLastViewed = $null + } + + if ($objLastViewed) + { + $obj | Add-Member -MemberType NoteProperty -Name LastViewed -Value $objLastViewed + $objLastViewed = $null + } + + if ($UserWhiteboard.meetingId) + { + $obj | Add-Member -MemberType NoteProperty -Name Meeting -Value $UserWhiteboard.meetingId + } + + # Add to the report + $Report += $obj + + # Cleanup + $obj = $null + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $e.Exception.Message -WarningAction Continue -ErrorAction Continue + #endregion ErrorHandler + } + + # Cleanup + $UserWhiteboards = $null + } + } + } + + end + { + # Dump the report to the Terminal + if ($Report) + { + $Report + } + else + { + Write-Warning -Message 'There is not Whiteboard to report' -WarningAction Continue -ErrorAction Continue + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Get-O365MailboxServerDatacenterLocation.ps1 b/Powershell/PowerShell-collection/Office365/Get-O365MailboxServerDatacenterLocation.ps1 new file mode 100644 index 0000000..c859119 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Get-O365MailboxServerDatacenterLocation.ps1 @@ -0,0 +1,211 @@ +function Get-O365MailboxServerDatacenterLocation +{ + <# + .SYNOPSIS + Determines the datacenter and location of an Exchange Online Server by name + + .DESCRIPTION + Determines the datacenter and location of an Exchange Online Server by name + Multiple Servers are supported. + + The Following info is returned: + ServerName = The server name you used + Location = City (if known) or country + Region = Region (e.g. EUR for Europe, or NAM for North America) + GDPR = Is the Region EUR (Europe) or not + + .PARAMETER ServerName + Server Name to check + + .EXAMPLE + PS C:\> Get-O365MailboxServerDatacenterLocation -ServerName AM3PR1001MB1421 + + Sample Result: + ServerName Location Region GDPR + ---------- -------- ------ ---- + AM3PR1001MB1421 Amsterdam, Netherlands EUR True + + The Server seems to be in Amsterdam, Netherlands (Europe) + + .EXAMPLE + PS C:\> Get-O365MailboxServerDatacenterLocation -ServerName 'AM3PR1001MB1421 (15.20.3890.032)' + + Sample Result: + ServerName Location Region GDPR + ---------- -------- ------ ---- + AM3PR1001MB1421 Amsterdam, Netherlands EUR True + + The Server seems to be in Amsterdam, Netherlands (Europe) + The Server name needs to be the first word in the string, the rest is ignored! + + .EXAMPLE + PS C:\> Get-O365MailboxServerDatacenterLocation -ServerName AZ3PR1001MB1421 + + Sample Result: + ServerName Location Region GDPR + ---------- -------- ------ ---- + AZ3PR1001MB1421 Unknown Unknown Unknown + + This is the result if the server location is unknown + + .EXAMPLE + PS C:\> Get-O365MailboxServerDatacenterLocation -ServerName 'AM3PR1001MB1421', 'AZ3PR1001MB1421' + + Sample Result: + ServerName Location Region GDPR + ---------- -------- ------ ---- + AM3PR1001MB1421 Amsterdam, Netherlands EUR True + AZ3PR1001MB1421 Unknown Unknown Unknown + + Query multiple servers at the same time + + .NOTES + This is something I wrote for myself: I want to get detailed informations about Exchange servers that I find in some of the Microsoft Office 365 Logs + + Limitation: + - Table of data-centers is static and may need to be expanded as Microsoft brings additional data-centers online + - If Microsoft decide to change the naming convention, the table of data-centers will become useless instantly + - The script works offline and does not check any plausibility (e.g. none existing servers, like in the examples above) + + The Following info is returned: + ServerName = The server name you used + Location = City (if known) or country + Region = Region (e.g. EUR for Europe, or NAM for North America) + GDPR = Is the Region EUR (Europe) or not - This is one of the key functions for me! + + Inspired by this blog post: https://adameyob.com/2018/03/30/exchange-online-woes + But my solution is slightly different: I use the server name I have from the logs to get the info + #> + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(Mandatory, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Server Name')] + [Alias('M365ServerName', 'MailboxServer', 'O365MailboxServerName')] + [string[]] + $ServerName + ) + + begin + { + # Run Garbage Collection + [gc]::Collect() + + # Create a new Hash-table + $Datacenter = (New-Object -TypeName Hashtable) + + # Fill the Hash-table + $Datacenter['AM'] = @('EUR', 'Amsterdam, Netherlands') + $Datacenter['BL'] = @('NAM', 'Virginia, USA') + $Datacenter['BN'] = @('NAM', 'Virginia, USA') + $Datacenter['BY'] = @('NAM', 'San Francisco, California, USA') + $Datacenter['CH'] = @('NAM', 'Chicago, Illinois, USA') + $Datacenter['CO'] = @('NAM', 'Quincy, Washington, USA') + $Datacenter['CP'] = @('LAM', 'Brazil') + $Datacenter['CY'] = @('NAM', 'Cheyenne, Wyoming, USA') + $Datacenter['DB'] = @('EUR', 'Dublin, Ireland') + $Datacenter['DM'] = @('NAM', 'Des Moines, Iowa, USA') + $Datacenter['GR'] = @('LAM', 'Brazil') + $Datacenter['HE'] = @('EUR', 'Finland') + $Datacenter['HK'] = @('APC', 'Hong Kong') + $Datacenter['KA'] = @('JPN', 'Japan') + $Datacenter['KL'] = @('APC', 'Kuala Lumpur, Malaysia') + $Datacenter['LO'] = @('GBR', 'London, England') + $Datacenter['ME'] = @('APC', 'Melbourne, Victoria, Australia') + $Datacenter['MM'] = @('GBR', 'Durham, England') + $Datacenter['MW'] = @('NAM', 'Quincy, Washington, USA') + $Datacenter['OS'] = @('JPN', 'Japan') + $Datacenter['PS'] = @('APC', 'Busan, South Korea') + $Datacenter['SG'] = @('APC', 'Singapore') + $Datacenter['SI'] = @('APC', 'Singapore') + $Datacenter['SN'] = @('NAM', 'San Antonio, Texas, USA') + $Datacenter['SY'] = @('APC', 'Sydney, New South Wales, Australia') + $Datacenter['TY'] = @('JPN', 'Japan') + $Datacenter['VI'] = @('EUR', 'Austria') + $Datacenter['YQ'] = @('CAN', 'Quebec City, Canada') + $Datacenter['YT'] = @('CAN', 'Toronto, Canada') + } + + process + { + $Result = (New-Object -TypeName System.Collections.Generic.List[System.Object]) + + foreach ($SingleServerName in $ServerName) + { + # Cleanup the Server name (Remove everything after the 1st word) + $SingleServerName = ($SingleServerName -split ' ')[0] + + # This is a bit nasty, but unknown cause errors (null pointer) + try + { + $ObjectRegion = $Datacenter[$($SingleServerName.SubString(0, 2))][0] + } + catch + { + # If you know the info, please let me know! + $ObjectRegion = 'Unknown' + } + + # This is a bit nasty, but unknown cause errors (null pointer) + try + { + $ObjectLocation = $Datacenter[$($SingleServerName.SubString(0, 2))][1] + } + catch + { + # If you know the info, please let me know! + $ObjectLocation = 'Unknown' + } + + switch ($ObjectRegion) + { + 'EUR' + { + $ObjectGDPR = $true + } + 'Unknown' + { + # Unknown triggers an internal investigation (find the location Info ASAP) + $ObjectGDPR = 'Unknown' + } + default + { + # That triggers an Alarm in my SIEM + $ObjectGDPR = $false + } + } + + # Keep the object in order! + $Object = [PSCustomObject][ordered]@{ + ServerName = $SingleServerName + Location = $ObjectLocation + Region = $ObjectRegion + GDPR = $ObjectGDPR + } + + # Add to the Output + $Result.Add($Object) + + # Cleanup + $Object = $null + $ObjectLocation = $null + $ObjectRegion = $null + $ObjectGDPR = $null + } + } + + end + { + # Dump to the Terminal + $Result + + # Cleanup + $Result = $null + $Datacenter = $null + + # Run Garbage Collection + [gc]::Collect() + } +} diff --git a/Powershell/PowerShell-collection/Office365/Get-Office365Endpoints.ps1 b/Powershell/PowerShell-collection/Office365/Get-Office365Endpoints.ps1 new file mode 100644 index 0000000..3907cdb --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Get-Office365Endpoints.ps1 @@ -0,0 +1,724 @@ +function Get-Office365Endpoints +{ + <# + .SYNOPSIS + Get the Office 365 Endpoint Information from Microsoft via the new RestFull Webservice (JSON) + + .DESCRIPTION + Microsoft updates the Office 365 IP address and FQDN entries at the end of each month and occasionally out of the cycle for operational or support requirements. + + This function uses the new JSON based Webserice instead of the old XML based one; the XML based service will be retired soon by Microsoft. + + The Function will compare the last downloaded version with the latest available online version, if there is no update available, the function does nothing. + If there is an update, the function will do what you told it to. If you want to enforce the download, just delete the O365_endpoints_*_latestversion.txt in your $Env:TEMP Directory. The * is a placeholder, for the Instance name. + + .PARAMETER Instance + The short name of the Office 365 service instance. + Valid: Worldwide, USGovDoD, USGovGCCHigh, China, Germany + The default is: Worldwide + + .PARAMETER Services + Valid items are All, Common, Exchange, SharePoint, Skype. + Because Common service area items are a prerequisite for all other service areas it is included every time - Adopted that from the Microsoft Statement; nevertheless, we disagree with the selection of Microsoft. There are way to many endpoints included here! + The default is: All + + .PARAMETER Tenant + Your Office 365 tenant name. + The web service takes your provided name and inserts it in parts of URLs that include the tenant name. + If you don't provide a tenant name, those parts of URLs have the wildcard character (*). + + .PARAMETER NoIPv6 + Query string parameter. Set this to true to exclude IPv6 addresses from the output, for example, if you don't use IPv6 in your network. + The default is FALSE + + .PARAMETER ExpressRoute + Only display endpoints that could be routed over ExpressRoute. + Default is: FALSE - All endpoints will be exported + + .PARAMETER Category + The connectivity category for the endpoint set. + Valid values are: All, Optimize, Allow, and Default. + Default is: 'All' + + .PARAMETER Required + This endpoint set is required to have connectivity for Office 365 to be supported. + Default is: FALSE + + .PARAMETER Output + What to return? + Values are: All, IPv4, IPv6, URLs + Default is: All + + .PARAMETER SkipVersionCheck + Force the download and ignore the existing version information + + .EXAMPLE + PS C:\> Get-Office365Endpoints.ps1 + + It gets the International (Worldwide) Office 365 URLs, IPv4, and IPv6 address ranges. + + .EXAMPLE + PS C:\> Get-Office365Endpoints.ps1 -Instance Germany + + It gets the Office 365 Germany URLs, IPv4 address ranges. It would also return IPv6, but IPv6 is not supported, at least not yet. + + .EXAMPLE + PS C:\> Get-Office365Endpoints.ps1 -Instance Germany -Category Optimize + + It gets the Office 365 Germany URLs, IPv4 address ranges. Only in the category 'Optimize'. It would also return IPv6, but IPv6 is not supported, at least not yet. + + .EXAMPLE + PS C:\> Get-Office365Endpoints.ps1 -Instance Worldwide -Services Exchange -Required + + It gets the International (Worldwide) Office 365 URLs, IPv4, and IPv6 address ranges for Exchange and everything to be supported (includes CDNs and other, even external, services). + + .EXAMPLE + PS C:\> Get-Office365Endpoints.ps1 -Instance Worldwide -Services Exchange -Required -Tenant 'contoso' + + It gets the International (Worldwide) Office 365 URLs, IPv4, and IPv6 address ranges for Exchange and everything to be supported (includes CDNs and other, even external, services); this example includes URLs for the tenant with the Name 'contoso'. + The Tenant based URLs are generated and not checked, so please make sure you use the correct name! + + .EXAMPLE + PS C:\> ((Get-Office365Endpoints.ps1 -Instance Worldwide -Services Exchange -Tenant 'contoso' -Output URLs -Required).url | Sort-Object -Unique) -join "," | Out-String + + It gets the International (Worldwide) Office 365 URLs, IPv4, and IPv6 address ranges for Exchange and everything to be supported (includes CDNs and other, even external, services); this example includes URLs for the tenant with the Name 'contoso'. + The Tenant based URLs are generated and not checked, so please make sure you use the correct name! ! + It just dumps the URLs in a comma separated (CSV) format. Useful for Proxy Servers. + + .EXAMPLE + PS C:\> ((Get-Office365Endpoints.ps1 -Instance Worldwide -Services Exchange -Tenant 'contoso' -Output URLs -Required -SkipVersionCheck).url | Sort-Object -Unique) -join "," | Out-String + + It gets the International (Worldwide) Office 365 URLs, IPv4, and IPv6 address ranges for Exchange and everything to be supported (includes CDNs and other, even external, services); this example includes URLs for the tenant with the Name 'contoso'. + The Tenant based URLs are generated and not checked, so please make sure you use the correct name! ! + It just dumps the URLs in a comma separated (CSV) format. Useful for Proxy Servers. + The SkipVersionCheck Switch enforce the Download, without checking the local version. + + .EXAMPLE + PS C:\> (((Get-Office365Endpoints.ps1 -Instance Worldwide -Services Exchange -Output IPv4) | Where-Object -FilterScript {$PSItem.tcpPorts -eq '587'}).ip | Sort-Object -Unique) -join "," | Out-String + + It gets the International (Worldwide) Office 365 IPv4 addresses for Exchange Submission (SMTP) Servers who use Port 587. It dumps a comma separated (CSV) format. Useful for Firewalls. + + .EXAMPLE + PS C:\> (((Get-Office365Endpoints.ps1 -Instance Worldwide -Services Exchange -Output IPv6) | Where-Object -FilterScript {$PSItem.tcpPorts -eq '25'}).ip | Sort-Object -Unique) -join "," | Out-String + + It gets the International (Worldwide) Office 365 IPv4 addresses for Exchange SMTP Servers who use Port 25. It dumps a comma separated (CSV) format. Useful for Firewalls. + + .EXAMPLE + PS C:\> (((Get-Office365Endpoints.ps1 -Instance Worldwide -Services Exchange -Output URLs) | Where-Object -FilterScript {$PSItem.notes -like '*Exchange Hybrid Configuration Wizard*' }).url | Sort-Object -Unique) -join "," | Out-String + + Get a List of Exchange Online URLs that you might need if you want to run the Exchange Hybrid Configuration Wizard. + + .EXAMPLE + PS C:\> ((Get-Office365Endpoints.ps1 -Instance Worldwide -Output 'IPv4' -ExpressRoute).ip | Sort-Object -Unique) -join "," | Out-String + + Get a List of IPv4 addresses for ExpressRoute configuration. + + .EXAMPLE + PS C:\> ((Get-Office365Endpoints.ps1 -Instance Worldwide -Output 'IPv6' -ExpressRoute).ip | Sort-Object -Unique) -join "," | Out-String + + Get a List of IPv6 addresses for ExpressRoute configuration. Please note: IPv6 is not supported with ExpressRoute in every Instance, (example: Germany) + + .EXAMPLE + PS C:\> ((Get-Office365Endpoints.ps1 -Instance Worldwide -NoIPv6).ip | Sort-Object -Unique) -join "," | Out-String + + Get a list of IP addresses and exclude IPv6. The benefit of this parameter is the NoIPv6 parameter: The call will exclude the IPv6 Data from the response, and that might be smarter than filter it. It might be handy if you do NOT use IPv6 within your network - If this is the case, you might miss the future of networking! Think about that, before ignoring IPv6. + + .EXAMPLE + $ExchangeOnlineSMTPEndpoints = (Get-Office365Endpoints.ps1 -Services Exchange) | Where-Object -FilterScript { + $PSItem.ip -and + $PSItem.DisplayName -eq 'Exchange Online' -and + $PSItem.tcpPorts -contains '25' + } + $ExchangeOnlineSMTPEndpoints.ip + + Retrieve endpoints for Exchange Online and filter on TCP port 25 + This is based on the following idea: http://www.powershell.no/exchange/online,office/365,powershell/2018/08/26/automate-office365-ip-address-handling.html + + .NOTES + Function that uses the new Microsoft Service. A few things are still missing or not rock solid. + However, we needed a solution to configure ExpressRoute now, so we started with some rework to use the new web service. + + This function is part of the commercial en.Office365 PowerShell Module - Distributed separately as OpenSource with a very flexible license (See below) + + Some parts of the script are based upon the example that Microsoft published on the info page of the new web service! + + .LINK + https://github.com/jhochwald/PowerShell-collection/blob/master/Office365/Get-Office365Endpoints.ps1 + + .LINK + https://hochwald.net/powershell-get-the-office-365-endpoint-information-from-microsoft/ + + .LINK + https://hochwald.net/powershell-function-to-get-the-office-365-urls-and-ip-address-ranges/ + + .LINK + https://support.office.com/en-us/article/managing-office-365-endpoints-99cab9d4-ef59-4207-9f2b-3728eb46bf9a#webservice + + .LINK + https://techcommunity.microsoft.com/t5/Office-365-Blog/Announcing-Office-365-endpoint-categories-and-Office-365-IP/ba-p/177638 + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateSet('Worldwide', 'USGovDoD', 'USGovGCCHigh', 'China', 'Germany', IgnoreCase = $true)] + [ValidateNotNullOrEmpty()] + [string] + $Instance = 'Worldwide', + [Parameter(ValueFromPipeline)] + [ValidateSet('All', 'Common', 'Exchange', 'SharePoint', 'Skype', IgnoreCase = $true)] + [ValidateNotNullOrEmpty()] + [Alias('ServiceAreas')] + [string] + $Services = 'All', + [Parameter(ValueFromPipeline)] + [Alias('TenantName')] + [string] + $Tenant = $null, + [Parameter(ValueFromPipeline)] + [switch] + $NoIPv6, + [Parameter(ValueFromPipeline)] + [switch] + $ExpressRoute, + [ValidateSet('All', 'Optimize', 'Allow', 'Default', IgnoreCase = $true)] + [string[]] + $Category, + [Parameter(ValueFromPipeline)] + [switch] + $Required, + [Parameter(ValueFromPipeline)] + [ValidateSet('All', 'IPv4', 'IPv6', 'URLs', IgnoreCase = $true)] + [string] + $Output = 'All', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('ForceDownload')] + [switch] + $SkipVersionCheck = $false + ) + + begin + { + #region MakeIPv6Plausible + if (($NoIPv6) -and ($Output -eq 'IPv6')) + { + # This makes no sense, and we totally ignore to do it! + Write-Error -Message 'The selected parameters make no sense; we cannot continue!' -ErrorAction Stop + + # We should never reach this point! + break + } + #endregion MakeIPv6Plausible + + #region CategoryTweaker + if ((! $Category) -or ($Category -eq 'All')) + { + Write-Verbose -Message 'We get all categories.' + + # Set to all + $Category += 'Optimize', 'Allow', 'Default' + } + #endregion CategoryTweaker + + #region TweakOutputHandler + + <# + TODO: Make a simpler solution for that! + #> + switch ($Output) + { + 'All' + { + Write-Verbose -Message 'Dump all Infos (IPv4, IPv6, and URLs)' + + $outIPv4 = $true + $outIPv6 = $true + $outURLs = $true + } + 'IPv4' + { + Write-Verbose -Message 'Dump IPv4 Infos' + + $outIPv4 = $true + $outIPv6 = $false + $outURLs = $false + } + 'IPv6' + { + Write-Verbose -Message 'Dump IPv6 Infos' + + $outIPv4 = $false + $outIPv6 = $true + $outURLs = $false + } + 'URLs' + { + Write-Verbose -Message 'Dump URLs Infos' + + $outIPv4 = $false + $outIPv6 = $false + $outURLs = $true + } + } + #endregion TweakOutputHandler + + #region ConfigurationVariables + # Web service root URL + $BaseURI = 'https://endpoints.office.com' + Write-Verbose -Message ('We use {0} as Base URL' -f $BaseURI) + + # Path where client ID and latest version number will be stored + <# + TODO: Move the Location to a parameter + #> + $datapath = $Env:TEMP + '\O365_endpoints_' + $Instance + '_latestversion.txt' + + Write-Verbose -Message ('We save the Endpoint Version Information to {0}' -f $datapath) + #endregion ConfigurationVariables + + #region LocalVersionChecker + # fetch client ID and version if data file exists; otherwise create new file + if (Test-Path -Path $datapath) + { + Write-Verbose -Message 'We get the information from Microsoft...' + + # Read the File + $content = (Get-Content -Path $datapath) + + # Get the Info + $clientRequestId = $content[0] + $lastVersion = $content[1] + + # Cleanup + $content = $null + } + else + { + Write-Verbose -Message 'Old version information file exists, start to gather the Info!' + + # Create a GUID + $clientRequestId = [GUID]::NewGuid().Guid + + # Dummy Data + $lastVersion = '0000000000' + + # Save the local info + try + { + @($clientRequestId, $lastVersion) | Out-File -FilePath $datapath -ErrorAction Stop + } + catch + { + # Write the complete error if we have verbose turned on + Write-Verbose -Message $_ + + # Our Error test + Write-Error -Message ('Unable to write Datafile: {0}' -f $datapath) -ErrorAction Stop + + # We should never reach this point! + break + } + } + #endregion LocalVersionChecker + + #region RemoteVersionChecker + # Call version method to check the latest version, and pull new data if version number is different + try + { + # Splat the parameters + $GetVersionParams = @{ + Uri = ($BaseURI + '/version/' + $Instance + '?clientRequestId=' + $clientRequestId) + Method = 'Get' + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + + Write-Verbose -Message ('We use {0} as request URI.' -f ($GetVersionParams.Uri)) + + $version = (Invoke-RestMethod @GetVersionParams) + } + catch + { + # Write the complete error if we have verbose turned on + Write-Verbose -Message $_ + + # Our Error test + Write-Error -Message 'Unable to get the new Office 365 Endpoint Information' -ErrorAction Stop + + # We should never reach this point! + break + } + #endregion RemoteVersionChecker + } + + process + { + #region VersionCompare + if (($SkipVersionCheck -eq $true) -or ($version.latest -gt $lastVersion)) + { + Write-Verbose -Message ('New version of Office 365 {0} endpoints detected' -f $Instance) + + # Write the new version number to the data file + try + { + @($clientRequestId, $version.latest) | Out-File -FilePath $datapath -ErrorAction Stop + } + catch + { + # Write the complete error if we have verbose turned on + Write-Verbose -Message $_ + + # Our Error test + Write-Error -Message ('Unable to write Datafile: {0}' -f $datapath) -ErrorAction Stop + + # We should never reach this point! + break + } + #endregion VersionCompare + + #region GetTheEndpoints + try + { + # Set the default URI + $requestURI = ($BaseURI + '/endpoints/' + $Instance + '?clientRequestId=' + $clientRequestId) + + switch ($Services) + { + 'All' + { + # We get all + } + 'Common' + { + # Append to the URI + $requestURI = ($requestURI + '&ServiceAreas=Common') + } + 'Exchange' + { + # Append to the URI + $requestURI = ($requestURI + '&ServiceAreas=Exchange') + } + 'SharePoint' + { + # Append to the URI + $requestURI = ($requestURI + '&ServiceAreas=SharePoint') + } + 'Skype' + { + # Append to the URI + $requestURI = ($requestURI + '&ServiceAreas=Skype') + } + } + + if ($Tenant) + { + # Append to the URI - Build URL for the Tenant + $requestURI = ($requestURI + '&TenantName=' + $Tenant) + } + + if ($NoIPv6) + { + # Append to the URI - Exclude IPv6 addresses from the output + $requestURI = ($requestURI + '&NoIPv6') + + Write-Verbose -Message 'IPv6 addresses are excluded from the output! IPv6 is the future, think about an adoption soon.' + } + + # Do our job and get the data via Rest Request + Write-Verbose -Message ('We request the following URI: {0}' -f $requestURI) + + $endpointSetsParams = @{ + Uri = $requestURI + Method = 'Get' + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $endpointSets = (Invoke-RestMethod @endpointSetsParams) + } + catch + { + # Write the complete error if we have verbose turned on + Write-Verbose -Message $_ + + # Our Error test + Write-Error -Message 'Unable to get the new Office 365 Endpoint Information' -ErrorAction Stop + + # We should never reach this point! + break + } + #endregion GetTheEndpoints + + #region FilterURLs + + if ($outURLs) + { + $flatUrls = $endpointSets | ForEach-Object -Process { + $endpointSet = $PSItem + $urls = $(if ($endpointSet.urls.Count -gt 0) + { + $endpointSet.urls + } + else + { + @() + } + ) + + # Cleanup + $urlCustomObjects = @() + + if ($endpointSet.category -in ($Category)) + { + $urlCustomObjects = $urls | ForEach-Object -Process { + # Ordered is slower, but we like it this way + [PSCustomObject][ordered]@{ + id = $endpointSet.id + serviceArea = $endpointSet.serviceArea + DisplayName = $endpointSet.serviceAreaDisplayName + url = $PSItem + tcpPorts = $endpointSet.tcpPorts + udpPorts = $endpointSet.udpPorts + expressRoute = $endpointSet.expressRoute + category = $endpointSet.category + required = $endpointSet.required + notes = $endpointSet.notes + } + } + } + + # Only ExpressRoute enabled Objects? + if ($ExpressRoute) + { + $urlCustomObjects = $urlCustomObjects | Where-Object -FilterScript { + $urlCustomObjects.expressRoute -eq $true + } + } + + # Only required to have connectivity for Office 365 to be supported + if ($Required) + { + $urlCustomObjects = $urlCustomObjects | Where-Object -FilterScript { + $urlCustomObjects.required -eq $true + } + } + + # Dump + $urlCustomObjects + } + } + #endregion FilterURLs + + #region FilterIPv4 + if ($outIPv4) + { + $flatIpv4 = $endpointSets | ForEach-Object -Process { + $endpointSet = $PSItem + $ips = $(if ($endpointSet.ips.Count -gt 0) + { + $endpointSet.ips + } + else + { + @() + } + ) + + # IPv4 strings have dots while IPv6 strings have colons + $IPv4 = $ips | Where-Object -FilterScript { + $PSItem -like '*.*' + } + + # Cleanup + $ipCustomObjects = @() + + if ($endpointSet.category -in ($Category)) + { + $ipCustomObjects = $IPv4 | ForEach-Object -Process { + # Ordered is slower, but we like it this way + [PSCustomObject][ordered]@{ + id = $endpointSet.id + serviceArea = $endpointSet.serviceArea + DisplayName = $endpointSet.serviceAreaDisplayName + ip = $PSItem + tcpPorts = $endpointSet.tcpPorts + udpPorts = $endpointSet.udpPorts + expressRoute = $endpointSet.expressRoute + category = $endpointSet.category + required = $endpointSet.required + notes = $endpointSet.notes + } + } + } + + # Dump + $ipCustomObjects + } + } + #endregion FilterIPv4 + + #region FilterIPv6 + if ($outIPv6) + { + $flatIpv6 = $endpointSets | ForEach-Object -Process { + $endpointSet = $PSItem + $ips = $(if ($endpointSet.ips.Count -gt 0) + { + $endpointSet.ips + } + else + { + @() + } + ) + + # IPv4 strings have dots while IPv6 strings have colons + $IPv6 = $ips | Where-Object -FilterScript { + $PSItem -like '*:*' + } + + # Cleanup + $ipCustomObjects = @() + + if ($endpointSet.category -in ($Category)) + { + $ipCustomObjects = $IPv6 | ForEach-Object -Process { + # Ordered is slower, but we like it this way + [PSCustomObject][ordered]@{ + id = $endpointSet.id + serviceArea = $endpointSet.serviceArea + DisplayName = $endpointSet.serviceAreaDisplayName + ip = $PSItem + tcpPorts = $endpointSet.tcpPorts + udpPorts = $endpointSet.udpPorts + expressRoute = $endpointSet.expressRoute + category = $endpointSet.category + required = $endpointSet.required + notes = $endpointSet.notes + } + } + } + + # Dump + $ipCustomObjects + } + } + #endregion FilterIPv4 + } + } + + end + { + if (($SkipVersionCheck -eq $true) -or ($version.latest -gt $lastVersion)) + { + #region DumpIPv4 + if ($outIPv4) + { + Write-Verbose -Message 'Office 365 IPv4 IP Address Ranges' + + ($flatIpv4 | Sort-Object -Property id) + } + #endregion DumpIPv4 + + #region DumpIPv6 + if ($outIPv6) + { + Write-Verbose -Message 'Office 365 IPv6 IP Address Ranges' + + ($flatIpv6 | Sort-Object -Property id) + } + #endregion DumpIPv6 + + #region DumpURLs + if ($outURLs) + { + Write-Verbose -Message 'Office 365 URLs' + + ($flatUrls | Sort-Object -Property id) + } + #endregion DumpURLs + } + else + { + #region DumpInfoNothing + <# + This 'else' loop is here as a placeholder in this script! + We use this in the commercial version (function within the commercial module) + #> + + Write-Output -InputObject ('The {0} Office 365 endpoints are up-to-date' -f $Instance) + #endregion DumpInfoNothing + } + } + + #region CHANGELOG + <# + CHANGELOG: + 0.8.6 - 2019.01-04: + [CHANGE] Converted back to a function to make it easier for me (no more need to adopt between my sources) + [ADD] Start to add regions + + 0.8.5 - 2018-10-04: + [FIX] Fix the Output to reflect the correct Instance name (PSMO365-48) + [ADD] Add -SkipVersionCheck Switch to force the download. As request by @mikes-gh in #4 in GitHub (PSMO365-49) + [FIX] Fix a view typos and errors + + 0.8.4 - 2018-08-29: + [ADD] Exchange Online Example added (Source http://www.powershell.no/exchange/online,office/365,powershell/2018/08/26/automate-office365-ip-address-handling.html) + [CHANGE] Tweaks (after internal code review and refactoring) + + 0.8.3 - 2018-08-20 - Unreleased: + [ADD] We added a few more verbose outputs. Verbose Implementation us based upon request. (PSMO365-43) + [CHANGE] Region name change + + 0.8.2 - 2018-08-19: + [ADD] Regions added to make the code more readable within code editors (PSMO365-47) + [FIX] A few typos in the descriptions where fixed - No change to any code or logic + + 0.8.1 - 2018-08-19: + [FIX] Add missing OutputType (PSMO365-41) + [CHANGE] datafile name tweaked (PSMO365-42) + [ADD] Missing NoIPv6 switch function implemented (PSMO365-44) + [ADD] New Example for NoIPv6 switch (PSMO365-45) + [ADD] A few more links + [ADD] Info about the datafile (PSMO365-42) + [ADD] Embed a few things as comment - Due to the separation from the Module + [ADD] This changelog within the code - Reflect the changes within the dedicated function (PSMO365-46) + + 0.8.0 - 2018-08-18: + [INIT] Initial public release + #> + #endregion CHANGELOG +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Get-OneDriveUsageReport.ps1 b/Powershell/PowerShell-collection/Office365/Get-OneDriveUsageReport.ps1 new file mode 100644 index 0000000..4eaddff --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Get-OneDriveUsageReport.ps1 @@ -0,0 +1,248 @@ +#requires -Version 3.0 -Modules Microsoft.Online.SharePoint.PowerShell + +<# + .SYNOPSIS + Generates a basic usage report for OneDrive for Business sites + + .DESCRIPTION + Generates a basic usage report for OneDrive for Business sites + The report will contain the following information: + - Owner (UPN) + - CurrentUsage (GB) + - Quota (GB) + - QuotaWarning (GB) + - QuotaType + - LastModified + - Status + + .PARAMETER TenantName + The Tenant name, like contoso if the tenant is contoso.onmicrosoft.com + vanity names, e.g. contoso.com, are NOT supported! + + .NOTES + Quick and dirty implementation to generate a simple CSV report file +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [ValidateNotNull()] + [Alias('Tenant', 'M365Name', 'M365TenantName')] + [string] + $TenantName = $null +) + +begin +{ + # Garbage Collection + [GC]::Collect() + + try + { + $paramImportModule = @{ + Name = 'Microsoft.Online.SharePoint.PowerShell' + DisableNameChecking = $true + NoClobber = $true + Force = $true + ErrorAction = 'SilentlyContinue' + WarningAction = 'Stop' + } + $null = (Import-Module @paramImportModule) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + + # Create the Connection URI + $AdminURL = ('https://' + $TenantName + '-admin.sharepoint.com') + + # Connect to SharePoint Online + $paramConnectSPOService = @{ + Url = $AdminURL + Region = 'Default' + ErrorAction = 'Stop' + } + $null = (Connect-SPOService @paramConnectSPOService) + + # Create new object + $Report = @() +} + +process +{ + $paramGetSPOSite = @{ + IncludePersonalSite = $true + Limit = 'all' + Filter = "Url -like '-my.sharepoint.com/personal/'" + ErrorAction = 'SilentlyContinue' + } + $Users = (Get-SPOSite @paramGetSPOSite | Select-Object -ExpandProperty Url) + + foreach ($User in $Users) + { + try + { + # Cleanup + $Stats = $null + $StatsReport = $null + + # Get the dedicated Info for the user + $paramGetSPOSite = @{ + Identity = $User + ErrorAction = 'Stop' + } + $Stats = (Get-SPOSite @paramGetSPOSite | Select-Object -Property LastContentModifiedDate, Owner, StorageUsageCurrent, StorageQuota, StorageQuotaWarningLevel, StorageQuotaType, Status) + + # Create the Reporting object + $StatsReport = [PSCustomObject]@{ + Owner = $Stats.Owner + CurrentUsage = '{0:F3}' -f ($Stats.StorageUsageCurrent / 1024) -as [decimal] + Quota = '{0:F0}' -f ($Stats.StorageQuota / 1024) -as [int] + QuotaWarning = '{0:F0}' -f ($Stats.StorageQuotaWarningLevel / 1024) -as [int] + QuotaType = $Stats.StorageQuotaType + LastModified = $Stats.LastContentModifiedDate + Status = $Stats.Status + } + + # Append the report + $Report += $StatsReport + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception + #endregion ErrorHandler + } + } +} + +end +{ + # Create a Timestamp (check if this is OK for you) + $TimeStamp = (Get-Date -Format yyyyMMdd_HHmmss) + + # Export the CSV Report + try + { + $paramExportCsv = @{ + Path = ('.\OneDriveUsageReport' + $TimeStamp + '.csv') + Force = $true + Encoding = 'UTF8' + Delimiter = ';' + NoTypeInformation = $true + ErrorAction = 'Stop' + } + ($Report | Sort-Object -Property CurrentUsage -Descending | Export-Csv @paramExportCsv) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + #endregion ErrorHandler + } + finally + { + # Cleanup + $Report = $null + + # Disconnect from SharePoint Online + $null = (Disconnect-SPOService -ErrorAction SilentlyContinue) + + # Garbage Collection + [GC]::Collect() + } +} + +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Initialize-ActivityAlertSet.ps1 b/Powershell/PowerShell-collection/Office365/Initialize-ActivityAlertSet.ps1 new file mode 100644 index 0000000..b2fb27a --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Initialize-ActivityAlertSet.ps1 @@ -0,0 +1,803 @@ +function Initialize-ActivityAlertSet +{ + <# + .SYNOPSIS + Create good practice Ruleset of Office 365 Activity Alert's + + .DESCRIPTION + Create good practice Ruleset of Office 365 Activity Alert's + You need a PowerShell connection to the Security and Compliance Center + + .PARAMETER NotifyUser + The NotifyUser parameter specifies the email addresses for notification messages. + You can specify internal and external email addresses (even mix them). + You can specify multiple email addresses separated by commas. + + .PARAMETER UserId + The UserId parameter specifies who you want to monitor. + If you specify a user's email address, you'll receive an email notification when the user performs the specified activity. + You can specify multiple email addresses separated by commas. + + If this parameter is blank ($null), you'll receive an email notification when any user in your organization performs the specified activity. + + Default is $null (Activity alert is triggered for any user) + + .PARAMETER EmailCulture + The EmailCulture parameter specifies the language of the notification email message. + Valid input for this parameter is a supported culture code value from the Microsoft .NET Framework CultureInfo class. + For example, de-DE for German, da-DK for Danish or ja-JP for Japanese. + + The default is en-US + + .EXAMPLE + PS C:\> Initialize-ActivityAlertSet -NotifyUser 'alert@contoso.com' + + Create good practice Ruleset of Office 365 Activity Alert's and send all alters to 'alert@contoso.com' + + .EXAMPLE + PS C:\> Initialize-ActivityAlertSet -NotifyUser 'alert@contoso.com -UserId 'john.doe@contoso.com' + + Create good practice Ruleset of Office 365 Activity Alert's and send all alters to 'alert@contoso.com', + only monitor the user 'john.doe@contoso.com' + + .EXAMPLE + PS C:\> Initialize-ActivityAlertSet -NotifyUser 'alert@contoso.com -UserId 'john.doe@contoso.com' -EmailCulture 'de-DE' + + Create good practice Ruleset of Office 365 Activity Alert's and send all alters to 'alert@contoso.com', + only monitor the user 'john.doe@contoso.com' and send all alters in German! + + .EXAMPLE + PS C:\> Initialize-ActivityAlertSet -NotifyUser 'alert@contoso.com -UserId 'john.doe@contoso.com', 'jane.doe@contoso.com' + + Create good practice Ruleset of Office 365 Activity Alert's and send all alters to 'alert@contoso.com', + only monitor the users 'john.doe@contoso.com' and 'jane.doe@contoso.com' + + .NOTES + Please Review all the settings carefully before your run the script! + + You must have a connection to the following Office 365 services: + - Security and Compliance Center + + All features should work with your default Office 365 Enterprise plan. Business plans are not tested! + + PLEASE NOTE: + This is really just a basic setup. It does NOT replace an security advice by a security consultant! + + .LINK + New-ActivityAlert + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'The NotifyUser parameter specifies the email addressesfor notification messages.')] + [ValidateNotNullOrEmpty()] + [Alias('AlertMail')] + [string[]] + $NotifyUser, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [AllowNull()] + [string[]] + $UserId = $null, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [cultureinfo] + $EmailCulture = 'en-US' + ) + + begin + { + if (-not (Get-Command -Name New-ProtectionAlert)) + { + Write-Error -Exception 'Not connected to the Office 365 Security & Compliance Center' -Message 'Use ''Connect-IPPSSession'' to connect to the Office 365 Security & Compliance Center' -Category OperationStopped -RecommendedAction 'Use ''Connect-IPPSSession'' to connect to the Office 365 Security & Compliance Center' -ErrorAction Stop + exit 1 + } + + Write-Output -InputObject "Create good practice Ruleset of Office 365 Activity Alert's" + } + + process + { + #region + try + { + $paramNewActivityAlert = @{ + Name = 'File and Page Alert' + Operation = 'Filemalwaredetected' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'SharePoint anti-virus engine detects malware in a file.' + Severity = 'Low' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'ThreatManagement' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Anonymous Links Alert' + Operation = 'Anonymouslinkcreated', 'Anonymouslinkupdated' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = "An anonymous link (also called an 'Anyone' link) was created/updated for a resource." + Severity = 'High' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataLossPrevention' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Anonymous Links Access Alert' + Operation = 'Anonymouslinkused' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = "An anonymous link (also called an 'Anyone' link) was used for a resource." + Severity = 'High' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataLossPrevention' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Sharing Alert' + Operation = 'Sharinginvitationcreated', 'Sharingpolicychanged' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = "User shared a resource in SharePoint Online or OneDrive for Business with a user who isn't in your organization's directory. A SharePoint or global administrator changed a SharePoint sharing policy." + Severity = 'Low' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataLossPrevention' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Access Alert' + Operation = 'Deviceaccesspolicychanged', 'Networkaccesspolicychanged' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Change in the unmanaged devices policy. Change in the location-based access policy (also called a trusted network boundary).' + Severity = 'Low' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Site Alert' + Operation = 'Sitecollectioncreated', 'Sitedeleted', 'Sitecollectionadminadded' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Creation of a new site collection OneDrive for Business site provisioned. A site was deleted.Site collection administrator or owner adds a person as a site collection administrator for a site.' + Severity = 'Low' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataGovernance' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Office Alert' + Operation = 'Officeondemandset' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Site administrator enables Office on Demand, which lets users access the latest version of Office desktop applications.' + Severity = 'Low' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'Others' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Mailbox Alert' + Operation = 'Add-MailboxPermission', 'Remove-MailboxPermission' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = "An administrator assigned/removed the FullAccess mailbox permission to a user (known as a delegate) to another person`'s mailbox" + Severity = 'Medium' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'AccessGovernance' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Password Alert' + Operation = 'Change user password.', 'Reset user password.', 'Set force change user password.' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'User password changes' + Severity = 'Medium' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'ThreatManagement' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Role Alert' + Operation = 'Add member to role.', 'Remove member from role.' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Added/Removed a user to an admin role in Office 365.' + Severity = 'Medium' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'AccessGovernance' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Company Information Alert' + Operation = 'Set company contact information.', 'Set company information.', 'Set password policy.', 'Remove partner from company.' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Change company information or password policy' + Severity = 'Medium' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataGovernance' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Domain Alert' + Operation = 'Add domain to company.', 'Update domain.' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Change of a custom domain in a tenant' + Severity = 'Low' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataGovernance' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Domain Remove Alert' + Operation = 'Remove domain from company.' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Remove of a custom domain in a tenant' + Severity = 'Medium' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataGovernance' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'First and Second Stage Recycle Bin' + Operation = @('filedeletedfirststagerecyclebin', 'filedeletedsecondstagerecyclebin', 'folderdeletedfirststagerecyclebin', 'folderdeletedsecondstagerecyclebin') + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Notify when items are deleted from first or second stage recycle bin' + Severity = 'High' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataLossPrevention' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewActivityAlert = @{ + Name = 'Transport Rules Monitoring Alerts' + Operation = 'New-TransportRule', 'Set-TransportRule', 'Remove-TransportRule' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = 'Creation, Modification and Deletion of Transport Rules' + Severity = 'High' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + RecordType = 'ExchangeAdmin' + Category = 'ThreatManagement' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + # MCAS might be the better option, but this requires proper licensing to fully use all of its functionality + $paramNewActivityAlert = @{ + Name = 'Sharepoint Folder or File is shared with an external party' + Operation = 'securelinkcreated' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = "A user has created a 'specific people link' to share a resource with a specific person. This target user may be someone who's external to your organization" + Severity = 'Medium' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataLossPrevention' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + # MCAS might be the better option, but this requires proper licensing to fully use all of its functionality + $paramNewActivityAlert = @{ + Name = 'Sharepoint Folder or File is shared company-wide' + Operation = 'CompanylinkCreated' + NotifyUser = $NotifyUser + UserId = $UserId + EmailCulture = $EmailCulture + Description = "User created a company-wide link to a resource. company-wide links can only be used by members in your organization. They can't be used by guests." + Severity = 'Low' + Type = 'Custom' + ErrorAction = 'Stop' + WarningAction = 'Continue' + Category = 'DataGovernance' + } + $null = (New-ActivityAlert @paramNewActivityAlert) + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + } + + end + { + Write-Output "Check the new Activity Alert's in your Office 365 Security & Compliance Center" + } +} +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Initialize-ProtectionAlertSet.ps1 b/Powershell/PowerShell-collection/Office365/Initialize-ProtectionAlertSet.ps1 new file mode 100644 index 0000000..a24a9e5 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Initialize-ProtectionAlertSet.ps1 @@ -0,0 +1,474 @@ +function Initialize-ProtectionAlertSet +{ + <# + .SYNOPSIS + Create good practice Ruleset of Office 365 Protection Alert's + + .DESCRIPTION + Create good practice Ruleset of Office 365 Protection Alert's + You need a PowerShell connection to the Security and Compliance Center + + .PARAMETER NotifyUser + The NotifyUser parameter specifies the email addresses for notification messages. + You can specify internal and external email addresses (even mix them). + You can specify multiple email addresses separated by commas. + + .PARAMETER UserId + The UserId parameter specifies who you want to monitor. + If you specify a user's email address, you'll receive an email notification when the user performs the specified activity. + You can specify multiple email addresses separated by commas. + + If this parameter is blank ($null), you'll receive an email notification when any user in your organization performs the specified activity. + + Default is $null (Activity alert is triggered for any user) + + .PARAMETER EmailCulture + The EmailCulture parameter specifies the language of the notification email message. + Valid input for this parameter is a supported culture code value from the Microsoft .NET Framework CultureInfo class. + For example, de-DE for German, da-DK for Danish or ja-JP for Japanese. + + The default is en-US + + .EXAMPLE + PS C:\> Initialize-ProtectionAlertSet -NotifyUser 'alert@contoso.com' + + Create good practice Ruleset of Office 365 Protection Alert's and send all alerts to 'alert@contoso.com' + + .EXAMPLE + PS C:\> Initialize-ProtectionAlertSet -NotifyUser 'alert@contoso.com -EmailCulture 'de-DE' + + Create good practice Ruleset of Office 365 Protection Alert's and send all alerts in German to 'alert@contoso.com' + + .NOTES + Please Review all the settings carefully before your run the script! + + You must have a connection to the following Office 365 services: + - Security and Compliance Center + + All features should work with your default Office 365 Enterprise plan. Business plans are not tested! + + PLEASE NOTE: + This is really just a basic setup. It does NOT replace an security advice by a security consultant! + + .LINK + New-ProtectionAlert + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'The NotifyUser parameter specifies the email addressesfor notification messages.')] + [ValidateNotNullOrEmpty()] + [Alias('AlertMail')] + [string[]] + $NotifyUser, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [cultureinfo] + $EmailCulture = 'en-US' + ) + + begin + { + if (-not (Get-Command -Name New-ProtectionAlert)) + { + Write-Error -Exception 'Not connected to the Office 365 Security & Compliance Center' -Message 'Use ''Connect-IPPSSession'' to connect to the Office 365 Security & Compliance Center' -Category OperationStopped -RecommendedAction 'Use ''Connect-IPPSSession'' to connect to the Office 365 Security & Compliance Center' -ErrorAction Stop + exit 1 + } + + Write-Output -InputObject "Create good practice Ruleset of Office 365 Protection Alert's" + } + + process + { + #region + try + { + # Office 365 E5 subscription or Office 365 E3 subscription with an Office 365 Threat Intelligence required + $paramNewProtectionAlert = @{ + Name = 'OneDrive deleted item threshold reached' + Category = 'DataGovernance' + NotifyUser = $NotifyUser + ThreatType = 'Activity' + Description = 'OneDrive deleted item threshold exceeds 50 in an hour' + AggregationType = 'SimpleAggregation' + Operation = 'FileDeleted' + Severity = 'Medium' + Filter = "Activity.SiteUrl -like '*-my.sharepoint.com/personal/*'" + Threshold = 50 + TimeWindow = 60 + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'MailRedirect created' + Category = 'DataLossPrevention' + ThreatType = 'Activity' + Operation = 'MailRedirect' + Severity = 'Medium' + NotifyUser = $NotifyUser + AggregationType = 'None' + Description = 'Email forward created' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'Granted Mailbox Permission' + Category = 'DataLossPrevention' + ThreatType = 'Activity' + Operation = 'AddMailboxPermission' + Severity = 'Medium' + NotifyUser = $NotifyUser + AggregationType = 'None' + Description = 'Granted Mailbox Permission' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'Outbound Phishing' + Category = 'ThreatManagement' + NotifyUser = $NotifyUser + ThreatType = 'Phish' + Description = 'Alert Outbound Phishing detected' + AggregationType = 'none' + Operation = $null + Filter = "(Mail.IsSystemZap -eq '0') -and (Mail.Direction -eq 'Outbound')" + Severity = 'High' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'Inbound Phishing' + Category = 'ThreatManagement' + NotifyUser = $NotifyUser + ThreatType = 'Phish' + Description = 'Alert Inbound Phishing detected' + AggregationType = 'none' + Operation = $null + Filter = "(Mail.IsSystemZap -eq '0') -and (Mail.Direction -eq 'Inbound')" + Severity = 'High' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'Office 365 Group deleted' + Category = 'DataGovernance' + NotifyUser = $NotifyUser + ThreatType = 'Activity' + Description = 'Alert if Office 365 Group is deleted' + AggregationType = 'none' + Operation = 'GroupRemoved' + Severity = 'Medium' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'Office 365 Group Created' + Category = 'DataGovernance' + NotifyUser = $NotifyUser + ThreatType = 'Activity' + Description = 'Alert if Office 365 Group is created' + AggregationType = 'none' + Operation = 'GroupCreated' + Severity = 'Medium' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'Sharing Policy Changed' + Category = 'DataLossPrevention' + NotifyUser = $NotifyUser + ThreatType = 'Activity' + Description = 'Alert if Sharing Policy is changed' + AggregationType = 'none' + Operation = 'SharingPolicyChanged' + Severity = 'High' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + + #region + try + { + $paramNewProtectionAlert = @{ + Name = 'Compromised Account Activity' + Category = 'DataLossPrevention' + NotifyUser = $NotifyUser + ThreatType = 'Activity' + Description = 'Alert if Compromised Account activity is detected' + AggregationType = 'none' + Operation = 'CompromisedAccount' + Severity = 'High' + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + New-ProtectionAlert @paramNewProtectionAlert + } + catch + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + Write-Warning -Message $info.Exception -WarningAction Continue -ErrorAction SilentlyContinue + } + #endregion + } + + end + { + Write-Output "Check the new Protection Alert's in your Office 365 Security & Compliance Center" + } +} +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Invoke-GetAzureADAuditSignInLogs.ps1 b/Powershell/PowerShell-collection/Office365/Invoke-GetAzureADAuditSignInLogs.ps1 new file mode 100644 index 0000000..908ea90 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Invoke-GetAzureADAuditSignInLogs.ps1 @@ -0,0 +1,246 @@ +<# + .SYNOPSIS + Get the AzureAD Audit Sign-In Logs + + .DESCRIPTION + Get the AzureAD Audit Sign-In Logs and create several CSV files + + .PARAMETER Days + Days to search + + .EXAMPLE + PS C:\> .\Invoke-GetAzureADAuditSignInLogs.ps1 + + Get the AzureAD Audit Sign-In Logs for the last 24 hours + + .EXAMPLE + PS C:\> .\Invoke-GetAzureADAuditSignInLogs.ps1 -Days 10 + + Get the AzureAD Audit Sign-In Logs for the last 10 days + + .LINK + Get-AzureADAuditSignInLogs + + .NOTES + Initial Beta Version +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNull()] + [ValidateNotNullOrEmpty()] + [Alias('DaysToSearch')] + [int] + $Days = 1 +) + +begin +{ + #region + if ($Days -lt 1) + { + Write-Error -Exception 'Value to low' -Message 'The given Days Value is below 1' -Category InvalidArgument -TargetObject $Days -RecommendedAction 'Select between 1 and 30' -ErrorAction Stop + Exit 1 + } + + if ($Days -gt 30) + { + Write-Error -Exception 'Value to high' -Message 'The given Days Value is above 30' -Category InvalidArgument -TargetObject $Days -RecommendedAction 'Select between 1 and 30' -ErrorAction Stop + Exit 1 + } + #endregion + + # You might want to tweak this a bit! + $null = (Disconnect-AzureAD -Confirm:$false -ErrorAction SilentlyContinue) + $null = (Remove-Module -Name AzureAD -Force -ErrorAction SilentlyContinue) + $null = (Import-Module -Name AzureADPreview -Force -ErrorAction SilentlyContinue) + $null = (Connect-AzureAD) + + # Garbage Collection + [GC]::Collect() + + # Cleanup + $filterAll = $null + $AzureAdSignInAll = $null + $AzureAdSignInFail = $null + $AzureAdSignInGood = $null + $AzureAdSignInAllCAfail = $null + $AzureAdSignInFailCAfail = $null + $AzureAdSignInGoodCAfail = $null + + # Define some defaults + $StartDateRaw = ((Get-Date).addDays(-$Days)) + $StartDate = ('{0}-{1}-{2}' -f $StartDateRaw.Year, $StartDateRaw.Month, $StartDateRaw.Day) + $StartDateRaw = $null + $EndDateRaw = (Get-Date) + $EndDate = ('{0}-{1}-{2}' -f $EndDateRaw.Year, $EndDateRaw.Month, $EndDateRaw.Day) + $EndDateRaw = $null +} + +process +{ + try + { + # Filtering + $filterAll = ('createdDateTime ge {0} and createdDateTime le {1}' -f $StartDate, $EndDate) + + # Get the Logs + $AzureAdSignInAll = (Get-AzureADAuditSignInLogs -Filter $filterAll) + + # Rest is done with filtering + $AzureAdSignInFail = ($AzureAdSignInAll | Where-Object -FilterScript { + $_.status.errorCode -ne 0 + }) + $AzureAdSignInGood = ($AzureAdSignInAll | Where-Object -FilterScript { + $_.status.errorCode -eq 0 + }) + + #region StructureData + $AzureAdSignInGood = ($AzureAdSignInGood | Select-Object -Property CreatedDateTime, UserPrincipalName, RiskState, AppId, ClientAppUsed, IpAddress, @{ + N = 'City' + E = { + $_.Location.City + } + }, @{ + N = 'CountryOrRegion' + E = { + $_.Location.CountryOrRegion + } + }, @{ + N = 'FailureReason' + E = { + $_.Status.FailureReason + } + }, ConditionalAccessStatus) + + $AzureAdSignInAll = ($AzureAdSignInAll | Select-Object -Property CreatedDateTime, UserPrincipalName, RiskState, AppId, ClientAppUsed, IpAddress, @{ + N = 'City' + E = { + $_.Location.City + } + }, @{ + N = 'CountryOrRegion' + E = { + $_.Location.CountryOrRegion + } + }, @{ + N = 'FailureReason' + E = { + $_.Status.FailureReason + } + }, ConditionalAccessStatus) + + $AzureAdSignInFail = ($AzureAdSignInFail | Select-Object -Property CreatedDateTime, UserPrincipalName, RiskState, AppId, ClientAppUsed, IpAddress, @{ + N = 'City' + E = { + $_.Location.City + } + }, @{ + N = 'CountryOrRegion' + E = { + $_.Location.CountryOrRegion + } + }, @{ + N = 'FailureReason' + E = { + $_.Status.FailureReason + } + }, ConditionalAccessStatus) + #endregion StructureData + + #region ConditionalAccessFilter + # BUG: Does not work as expected + $AzureAdSignInAllCAfail = ($AzureAdSignInAll | Where-Object -FilterScript { + (($_.ConditionalAccessStatus -ne 'success') -and ($_.ConditionalAccessStatus -ne 'notApplied')) + }) + + $AzureAdSignInFailCAfail = ($AzureAdSignInFail | Where-Object -FilterScript { + (($_.ConditionalAccessStatus -ne 'success') -and ($_.ConditionalAccessStatus -ne 'notApplied')) + }) + + $AzureAdSignInGoodCAfail = ($AzureAdSignInGood | Where-Object -FilterScript { + (($_.ConditionalAccessStatus -ne 'success') -and ($_.ConditionalAccessStatus -ne 'notApplied')) + }) + #endregion ConditionalAccessFilter + + $TimeStamp = Get-Date -Format yyyyMMdd_HHmmss + + # TODO: Make it a parameter + $ExportPath = ('C:\scripts\PowerShell\exports\AzureADSignInAudit') + + if (-not (Test-Path -Path $ExportPath)) + { + $null = (New-Item -Path $ExportPath -ItemType Directory -Force) + } + + #region Export + $null = ($AzureAdSignInAll | Export-Csv -Path ($ExportPath + '\AllSignInAuditLogs_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8) + + $null = ($AzureAdSignInFail | Export-Csv -Path ($ExportPath + '\FailSignInAuditLogs_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8) + + $null = ($AzureAdSignInGood | Export-Csv -Path ($ExportPath + '\GoodSignInAuditLogs_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8) + + if ($AzureAdSignInAllCAfail) + { + $null = ($AzureAdSignInAllCAfail | Export-Csv -Path ($ExportPath + '\AllSignInAuditLogs_CAFAIL_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8) + } + + if ($AzureAdSignInFailCAfail) + { + $null = ($AzureAdSignInFailCAfail | Export-Csv -Path ($ExportPath + '\FailSignInAuditLogs_CAFAIL_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8) + } + + if ($AzureAdSignInGoodCAfail) + { + $null = ($AzureAdSignInGoodCAfail | Export-Csv -Path ($ExportPath + '\GoodSignInAuditLogs_CAFAIL_' + $TimeStamp + '.csv') -NoTypeInformation -Force -Encoding UTF8) + } + #endregion Export + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + finally + { + # Cleanup + $filterAll = $null + $AzureAdSignInAll = $null + $AzureAdSignInFail = $null + $AzureAdSignInGood = $null + $AzureAdSignInAllCAfail = $null + $AzureAdSignInFailCAfail = $null + $AzureAdSignInGoodCAfail = $null + + # Garbage Collection + [GC]::Collect() + } +} diff --git a/Powershell/PowerShell-collection/Office365/LICENSE b/Powershell/PowerShell-collection/Office365/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Office365/ReplaceDomainForAllUnifiedGroups.ps1 b/Powershell/PowerShell-collection/Office365/ReplaceDomainForAllUnifiedGroups.ps1 new file mode 100644 index 0000000..71e0ec7 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/ReplaceDomainForAllUnifiedGroups.ps1 @@ -0,0 +1,101 @@ +<# + .SYNOPSIS + Replace the Domain for all UnifiedGroups (and Microsoft Teams) Primary SMTP Address + + .DESCRIPTION + Replace the Domain for all UnifiedGroups (and Microsoft Teams) Primary SMTP Address + + .PARAMETER OldDomain + The old Domain (e.g. contoso.com) + + .PARAMETER NewDomain + The new Domain (e.g. contoso.net) + + .EXAMPLE + PS C:\> .\ReplaceDomainForAllUnifiedGroups.ps1 -OldDomain 'contoso.com' -NewDomain 'contoso.net' + + Replace the Primary SMTP Addresses for all UnifiedGroups (and Microsoft Teams) that are in the domain 'contoso.com' with the someone in the Domain 'contoso.net' + e.g. if an old address was myTeam@contoso.com would end up as myTeam@contoso.new + + .LINK + https://docs.microsoft.com/en-us/powershell/exchange/exchange-online/connect-to-exchange-online-powershell/connect-to-exchange-online-powershell?view=exchange-ps + + .LINK + http://hochwald.net + + .NOTES + Quick and dirty approach, without any real Error handling. + A friend asked me for a solution after a merger to replace all Primary SMTP Addresses and get rif of the old domain (legal requirement in this case) + + You need be be connected to an Exchange Online Session (NOT part of this script). +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess = $true)] +param +( + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateNotNullOrEmpty()] + [Alias('DomainToReplace')] + [string] + $OldDomain, + [Parameter(Mandatory = $true, + ValueFromPipeline = $true, + ValueFromPipelineByPropertyName = $true)] + [ValidateNotNullOrEmpty()] + [string] + $NewDomain +) + +begin +{ + $OldMailFilter = ('@' + $OldDomain) + + # Cleanup + $AllUnifiedGroups = $null +} + +process +{ + $AllUnifiedGroups = (Get-UnifiedGroup | Where-Object -FilterScript { + $_.PrimarySmtpAddress -like ('*' + $OldMailFilter) + } | Select-Object -Property Identity, DisplayName, PrimarySmtpAddress) + + if ($AllUnifiedGroups) + { + foreach ($item in $AllUnifiedGroups) + { + if ($item.PrimarySmtpAddress -like ('*' + $OldMailFilter)) + { + $OldMailAddress = $null + $OldMailAddress = (($item).PrimarySmtpAddress) + + $NewMailAddress = $null + $NewMailAddress = ($OldMailAddress.Replace($OldMailFilter, ('@' + $NewDomain))) + Write-Verbose -Message ('Replace: {0} with: {1}' -f $OldMailAddress, $NewMailAddress) + + # Add the new Address + $null = (Set-UnifiedGroup -Identity (($item).Identity) -EmailAddresses: @{ + Add = $NewMailAddress + } -Confirm:$false) + + # Make new Address the primary SMTP address + $null = (Set-UnifiedGroup -Identity (($item).Identity) -PrimarySmtpAddress $NewMailAddress -Confirm:$false) + + # Remove the old SMTP Address + $null = (Set-UnifiedGroup -Identity (($item).Identity) -EmailAddresses: @{ + Remove = $OldMailAddress + } -Confirm:$false) + } + else + { + Write-Warning -Message ('Sorry, the PrimarySmtpAddress of {0} is not in {1}' -f $item.DisplayName, $OldDomain) + } + } + } + else + { + Write-Output -InputObject 'Nothing to do!!!' + } +} diff --git a/Powershell/PowerShell-collection/Office365/Set-AzureADNamingPolicyForOffice365Groups.ps1 b/Powershell/PowerShell-collection/Office365/Set-AzureADNamingPolicyForOffice365Groups.ps1 new file mode 100644 index 0000000..ea6a534 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Set-AzureADNamingPolicyForOffice365Groups.ps1 @@ -0,0 +1,220 @@ +#requires -Version 3.0 -Modules AzureADPreview + +<# + .SYNOPSIS + Create or modify a Azure AD Naming Policy for Office 365 Groups + + .DESCRIPTION + Create or modify a Azure AD Naming Policy for Office 365 Groups, these groups (a/k/a Unified Groups) are the base for Microsoft Teams and other Microsoft 365 services. + + .PARAMETER BlockedWordsFile + CSV with your blacklisted names, 5.000 word is the Office 365 maximum + + .PARAMETER ApplyDefaults + Apply some basics and defaults + + .EXAMPLE + PS C:\> .\Set-AzureADNamingPolicyForOffice365Groups.ps1 + + Create or modify a Azure AD Naming Policy for Office 365 Groups + + .EXAMPLE + PS C:\> .\Set-AzureADNamingPolicyForOffice365Groups.ps1 -Verbose + + Create or modify a Azure AD Naming Policy for Office 365 Groups + + .EXAMPLE + PS C:\> .\Set-AzureADNamingPolicyForOffice365Groups.ps1 -ApplyDefaults + + Create or modify a Azure AD Naming Policy for Office 365 Groups and apply some basics and defaults + + .EXAMPLE + PS C:\> .\Set-AzureADNamingPolicyForOffice365Groups.ps1 -ApplyDefaults -Verbose + + Create or modify a Azure AD Naming Policy for Office 365 Groups and apply some basics and defaults + + .NOTES + Nothing fancy, just a modified version of the Microsoft script. + + Please review the setting and check if my values match your requirements. + + If you create the new Group "Development", the Name becomes: + GRP_Development_Frankfurt + + This is based on my default naming convention: 'GRP_[GroupName]_[Office]' - Change it below to match your own naming convention! + + If you create the new Group "Payroll" it will fail! The Word "Payroll" is blacklisted! + + Please note: You need to have a AzureAD Premium P1 (or Higher) License, or any license option that contains AzureAD Premium P1 or P2 + + .LINK + https://docs.microsoft.com/en-us/microsoft-365/admin/create-groups/groups-naming-policy?view=o365-worldwide#how-to-set-up-the-naming-policy-in-azure-ad-powershell +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowNull()] + [AllowEmptyString()] + [Alias('File', 'Path')] + [string] + $BlockedWordsFile = '.\BlockedWords.csv', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [switch] + $ApplyDefaults +) + +begin +{ + # Remove the regular Module + $paramRemoveModule = @{ + Name = 'AzureAD' + Force = $true + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + } + $null = (Remove-Module @paramRemoveModule) + + # Do we have a CSV File? + if (Test-Path -Path $BlockedWordsFile -ErrorAction SilentlyContinue) + { + # Fine, let us import the CSV File + $paramImportCsv = @{ + Path = $BlockedWordsFile + Encoding = 'UTF8' + ErrorAction = 'Stop' + } + $BlockedWordsImport = (Import-Csv @paramImportCsv) + + # Transfer the values into the list + [string]$BlockedWords = ($BlockedWordsImport.BlockedWords -join ', ') + + # Cleanup + $BlockedWordsImport = $null + } + else + { + # No CSV, let us use some defaults + [string]$BlockedWords = 'Payroll,CEO,HR,hochwald' + } + + # Prefix and Suffix for the Unified Groups + <# + Valid suffix values are: + [Company] + [CountryOrRegion] + [Department] + [Office] + [StateOrProvince] + [Title] + #> + $PrefixSuffix = 'GRP_[GroupName]_[Office]' + + # Connect to your AzureAD tenant, if needed + try + { + $null = (Get-AzureADDomain -ErrorAction Stop) + } + catch + { + $null = (Connect-AzureAD) + } +} + +process +{ + try + { + # Get the existing template + $template = (Get-AzureADDirectorySettingTemplate -ErrorAction Stop | Where-Object -FilterScript { + $_.displayname -eq 'group.unified' + }) + + # Modify the settings + $settingsCopy = $template.CreateDirectorySetting() + + # Create a new setting + $paramNewAzureADDirectorySetting = @{ + DirectorySetting = $settingsCopy + ErrorAction = 'Stop' + } + $null = (New-AzureADDirectorySetting @paramNewAzureADDirectorySetting) + } + catch + { + Write-Verbose -Message 'Looks like we have the Settings...' + } + finally + { + # Get the settings + $settingsObjectID = (Get-AzureADDirectorySetting | Where-Object -Property Displayname -Value 'Group.Unified' -EQ | Select-Object -ExpandProperty id) + } + + # Read the settings + $settingsCopy = (Get-AzureADDirectorySetting -Id $settingsObjectID) + + # Modify the settings + $settingsCopy['PrefixSuffixNamingRequirement'] = $PrefixSuffix + $settingsCopy['CustomBlockedWordsList'] = $BlockedWords + + # Apply some basics and defaults + if ($ApplyDefaults) + { + $settingsCopy['EnableMSStandardBlockedWords'] = $true + $settingsCopy['AllowGuestsToBeGroupOwner'] = $false + $settingsCopy['AllowGuestsToAccessGroups'] = $true + } + + + # Apply the settings + $paramSetAzureADDirectorySetting = @{ + Id = $settingsObjectID + DirectorySetting = $settingsCopy + ErrorAction = 'Stop' + } + $null = (Set-AzureADDirectorySetting @paramSetAzureADDirectorySetting) +} + +end +{ + # Get the Info + $Info = (Get-AzureADDirectorySetting -Id $settingsObjectID | Select-Object -ExpandProperty Values) + + # Dump the Info + $Info + + # Cleanup + $Info = $null +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Set-MicrosoftNewWhiteboardOwner.ps1 b/Powershell/PowerShell-collection/Office365/Set-MicrosoftNewWhiteboardOwner.ps1 new file mode 100644 index 0000000..e3f32ab --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Set-MicrosoftNewWhiteboardOwner.ps1 @@ -0,0 +1,284 @@ +#requires -Version 3.0 -Modules AzureAD, WhiteboardAdmin +function Set-MicrosoftNewWhiteboardOwner +{ + <# + .SYNOPSIS + Set the owner for a a given Microsoft Whiteboard + + .DESCRIPTION + Set the owner for a a given Microsoft Whiteboard + + .PARAMETER WhiteboardId + The Whiteboard for which the owner is being changed. + + .PARAMETER OwnerId + The ID of the previous owner. + + .PARAMETER OwnerName + The UserPrincipalName of the previous owner. + + .PARAMETER NewOwnerId + The ID of the new owner. + + .PARAMETER NewOwnerName + The UserPrincipalName of the new owner. + + .PARAMETER All + Transfer ownership of all Whiteboards owned by a user to another user. + + .EXAMPLE + PS C:\> Set-MicrosoftNewWhiteboardOwner -WhiteboardId 'ad8d4e1b-45c9-4ff8-9757-77086f1b3fec' -OwnerId 'c85245cf-d5d9-4286-968f-6f95d46a885f' -NewOwnerId '7ff1141a-d6fa-401b-a7e5-0f8c6dd64aba' + + Transfers the ownership of the Whiteboard with the ID 'ad8d4e1b-45c9-4ff8-9757-77086f1b3fec' from UserID 'c85245cf-d5d9-4286-968f-6f95d46a885f' the the new owner with the ID '7ff1141a-d6fa-401b-a7e5-0f8c6dd64aba' + + .EXAMPLE + PS C:\> Set-MicrosoftNewWhiteboardOwner -WhiteboardId 'ad8d4e1b-45c9-4ff8-9757-77086f1b3fec' -OwnerName 'john.doe@contoso.com' -NewOwnerName 'jane.doe@contoso.com' + + Transfers the ownership of the Whiteboard with the ID 'ad8d4e1b-45c9-4ff8-9757-77086f1b3fec' from User 'john.doe@contoso.com' the the new owner 'jane.doe@contoso.com' + + .EXAMPLE + PS C:\> Set-MicrosoftNewWhiteboardOwner -All -OwnerId 'c85245cf-d5d9-4286-968f-6f95d46a885f' -NewOwnerId '7ff1141a-d6fa-401b-a7e5-0f8c6dd64aba' + + Transfers the ownership of the Whiteboards from the Owner with the ID 'c85245cf-d5d9-4286-968f-6f95d46a885f' the the new owner with the ID '7ff1141a-d6fa-401b-a7e5-0f8c6dd64aba' + This might be a use case for off boarding + + .EXAMPLE + PS C:\> Set-MicrosoftNewWhiteboardOwner -All -OwnerName 'john.doe@contoso.com' -NewOwnerName 'jane.doe@contoso.com' + + Transfers the ownership of the Whiteboards from the Owner 'john.doe@contoso.com' the the new owner 'jane.doe@contoso.com' + This might be a use case for off boarding + + .OUTPUTS + bool + + .NOTES + Hard to automate: The WhiteboardAdmin does not have a connect function and will always prompt for auth (and then cache the credentials used to connect). + All transfered Whiteboards are then shared between both, the old and the new owner! + + .LINK + Get-MicrosoftWhiteboardReport + + .LINK + Invoke-TransferAllWhiteboards + + .LINK + Set-WhiteboardOwner + + .LINK + https://www.powershellgallery.com/packages/WhiteboardAdmin/ + #> + + [CmdletBinding(DefaultParameterSetName = 'UseID', + ConfirmImpact = 'Low', + SupportsShouldProcess)] + [OutputType([bool], ParameterSetName = 'UseID')] + [OutputType([bool], ParameterSetName = 'UseName')] + [OutputType([bool])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('Whiteboard')] + [string] + $WhiteboardId = $null, + [Parameter(ParameterSetName = 'UseID', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'The ID of the previous owner.')] + [ValidateNotNullOrEmpty()] + [Alias('OldOwnerId')] + [string] + $OwnerId, + [Parameter(ParameterSetName = 'UseName', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'The UserPrincipalName of the previous owner.')] + [Alias('OwnerUserPrincipalName', 'OwnerUserPrincipal')] + [string] + $OwnerName, + [Parameter(ParameterSetName = 'UseID', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'The ID of the new owner.')] + [ValidateNotNullOrEmpty()] + [string] + $NewOwnerId, + [Parameter(ParameterSetName = 'UseName', HelpMessage = 'The UserPrincipalName of the new owner.', + Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('NewOwnerUserPrincipalName', 'NewOwnerUserPrincipal')] + [string] + $NewOwnerName, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [switch] + $All + ) + + begin + { + # Check if one of the required parameters is present + if ((-not (($PsCmdlet.MyInvocation.BoundParameters['All']))) -and (-not ($WhiteboardId))) + { + Write-Error -Message 'No WhiteboardId to transfer found and -All was not given!' -Category NotSpecified -TargetObject $WhiteboardId -RecommendedAction 'Specify -All or the WhiteboardId to transfer' -ErrorAction Stop + + # Only here to catch a global ErrorAction overwrite + exit 1 + } + + try + { + try + { + $null = (Get-AzureADTenantDetail -ErrorAction Stop) + } + catch + { + Connect-AzureAD + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + } + + process + { + $TargetObject = if (($PsCmdlet.MyInvocation.BoundParameters['All']).IsPresent) + { + 'all Whiteboards' + } + else + { + $WhiteboardId + } + + if ($PsCmdlet.ShouldProcess($TargetObject, 'Transfer ownership')) + { + try + { + switch ($PsCmdlet.ParameterSetName) + { + 'UseID' + { + if (($PsCmdlet.MyInvocation.BoundParameters['All']).IsPresent) + { + Invoke-TransferAllWhiteboards -OldOwnerId $OwnerId -NewOwnerId $NewOwnerId -ErrorAction Stop -Confirm:$false + } + else + { + Set-WhiteboardOwner -WhiteboardId $WhiteboardId -OldOwnerId $OwnerId -NewOwnerId $NewOwnerId -ErrorAction Stop -Confirm:$false + } + break + } + 'UseName' + { + $OwnerId = (Get-AzureADUser -Filter ("userPrincipalName eq '{0}'" -f $OwnerName) | Select-Object -ExpandProperty ObjectId) + $NewOwnerId = (Get-AzureADUser -Filter ("userPrincipalName eq '{0}'" -f $NewOwnerName) | Select-Object -ExpandProperty ObjectId) + + if (($PsCmdlet.MyInvocation.BoundParameters['All']).IsPresent) + { + Invoke-TransferAllWhiteboards -OldOwnerId $OwnerId -NewOwnerId $NewOwnerId -ErrorAction Stop -Confirm:$false + } + else + { + Set-WhiteboardOwner -WhiteboardId $WhiteboardId -OldOwnerId $OwnerId -NewOwnerId $NewOwnerId -ErrorAction Stop -Confirm:$false + } + break + } + } + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = 'Stop' + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # Only here to catch a global ErrorAction overwrite + exit 1 + #endregion ErrorHandler + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + Copyright (c) 2021, enabling Technology + All rights reserved. + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Set-Office365GroupMailAddress.ps1 b/Powershell/PowerShell-collection/Office365/Set-Office365GroupMailAddress.ps1 new file mode 100644 index 0000000..b70dc6b --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Set-Office365GroupMailAddress.ps1 @@ -0,0 +1,199 @@ +function Set-Office365GroupMailAddress +{ + <# + .SYNOPSIS + Add or change Office 365 Group or Team Email Address + + .DESCRIPTION + Add or change Office 365 Group or Team Email Address + + .PARAMETER OldDomain + Old Domain Name, Format is: DOMAIN.TLD + e.g. contoso.com + + .PARAMETER NewDomain + NEW Domain Name, Format is: DOMAIN.TLD + e.g. contoso.net + + .PARAMETER MakeNewPrimary + Will the new Mail address be the new Primary SMTP Address? + + .PARAMETER RemoveOld + Should the old Primary SMTP Address be removed? + Please note: You must make another one to your Primary SMTP Address before you do this! + + .EXAMPLE + PS C:\> Set-Office365GroupMailAddress -OldDomain 'contoso.onmicrosoft.com' -NewDomain 'contoso.com' + + If the existing Primary SMTP Address is 'dummy@contoso.onmicrosoft.com', this will add 'dummy@contoso.com' as alias. + + .EXAMPLE + PS C:\> Set-Office365GroupMailAddress -OldDomain 'contoso.com' -NewDomain 'contoso.net' -MakeNewPrimary + + If the existing Primary SMTP Address is 'dummy@contoso.com', this will add 'dummy@contoso.com' as alias, + and make it the new Primary SMTP Address + + .EXAMPLE + PS C:\> Set-Office365GroupMailAddress -OldDomain 'contoso.com' -NewDomain 'contoso.net' -MakeNewPrimary -RemoveOld + + If the existing Primary SMTP Address is 'dummy@contoso.com', this will add 'dummy@contoso.com' as alias, + and make it the new Primary SMTP Address and removes the old address + + .EXAMPLE + PS C:\> Set-Office365GroupMailAddress -OldDomain 'contoso.com' -NewDomain 'contoso.net' -MakeNewPrimary -RemoveOld -WhatIf + + If the existing Primary SMTP Address is 'dummy@contoso.com', this will add 'dummy@contoso.com' as alias, + and make it the new Primary SMTP Address and removes the old address + + Will simulate the execution (WhatIf is present) + + .EXAMPLE + PS C:\> Set-Office365GroupMailAddress -OldDomain 'contoso.com' -NewDomain 'contoso.net' -MakeNewPrimary -RemoveOld -Verbose + + If the existing Primary SMTP Address is 'dummy@contoso.com', this will add 'dummy@contoso.com' as alias, + and make it the new Primary SMTP Address and removes the old address. + + The Process will be verbose (Verbose is present) + + .NOTES + Initial public Release! + + Might become handy if you like to convert all DOMAIN.onmicrosoft.com addresses to your own domain, + or if you decide to go with a new external mail domain. + #> + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [string] + $OldDomain = 'contoso.com', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [string] + $NewDomain = 'contoso.net', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('MakePrimary')] + [switch] + $MakeNewPrimary = $null, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('RemoveOldDomain', 'Remove', 'Cleanup')] + [switch] + $RemoveOld = $null + ) + + begin + { + # Save the infos from the switches + $IsVerbose = (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + $IsWhatIf = (($PSCmdlet.MyInvocation.BoundParameters['WhatIf']).IsPresent) + + # Build the filter strings + $OldDomainString = ('@' + $OldDomain) + $NewDomainString = ('@' + $NewDomain) + + # Cleanup + $WrongGroups = $null + + # Get all matching Groups + $WrongGroups = (Get-UnifiedGroup -ErrorAction Stop -Verbose:$IsVerbose | Where-Object -FilterScript { + $_.PrimarySmtpAddress -like ('*' + $OldDomainString) + }) + } + + process + { + foreach ($item in $WrongGroups) + { + # Replace within the string + $NewPrimarySmtpAddress = ($item.PrimarySmtpAddress).Replace($OldDomainString, $NewDomainString) + + #region AddEmailAddresses + $paramSetUnifiedGroup = @{ + Identity = ($item.Name) + EmailAddresses = @{ + Add = $NewPrimarySmtpAddress + } + ErrorAction = 'Continue' + WhatIf = $IsWhatIf + Verbose = $IsVerbose + Confirm = $false + } + $null = (Set-UnifiedGroup @paramSetUnifiedGroup) + #endregion AddEmailAddresses + + #region SetPrimarySmtpAddress + if ($MakeNewPrimary) + { + $paramSetUnifiedGroup = @{ + Identity = ($item.Name) + PrimarySmtpAddress = $NewPrimarySmtpAddress + ErrorAction = 'Continue' + WhatIf = $IsWhatIf + Verbose = $IsVerbose + Confirm = $false + } + $null = (Set-UnifiedGroup @paramSetUnifiedGroup) + } + #endregion SetPrimarySmtpAddress + + #region RemoveOldAddress + if ($RemoveOld) + { + $paramSetUnifiedGroup = @{ + Identity = ($item.Name) + EmailAddresses = @{ + Remove = ($item.PrimarySmtpAddress) + } + ErrorAction = 'Continue' + WhatIf = $IsWhatIf + Verbose = $IsVerbose + Confirm = $false + } + $null = (Set-UnifiedGroup @paramSetUnifiedGroup) + } + #endregion RemoveOldAddress + } + } + + end + { + # Cleanup + $WrongGroups = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/Set-bdcMsolMFAState.ps1 b/Powershell/PowerShell-collection/Office365/Set-bdcMsolMFAState.ps1 new file mode 100644 index 0000000..4676df2 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/Set-bdcMsolMFAState.ps1 @@ -0,0 +1,135 @@ +#requires -Version 3.0 -Modules MSOnline +function Set-bdcMsolMFAState +{ + <# + .SYNOPSIS + Convert users from per-user MFA to Conditional Access based MFA + + .DESCRIPTION + Convert users from per-user MFA to Conditional Access based MFA + + .PARAMETER ObjectId + ObjectId of the Office 365 User + + .PARAMETER UserPrincipalName + User Principal Name of the Office 365 User + + .PARAMETER State + MFA State ('Disabled','Enabled', or 'Enforced') + Default is Disabled + + .EXAMPLE + Set-bdcMsolMFAState -ObjectId Value -UserPrincipalName john.doe@contoso.com -State Enabled + Enabled MFA for john.doe@contoso.com + + .EXAMPLE + Set-bdcMsolMFAState -ObjectId Value -UserPrincipalName john.doe@contoso.com -State Enabled + Enforces MFA for john.doe@contoso.com + + .EXAMPLE + Set-bdcMsolMFAState -ObjectId Value -UserPrincipalName john.doe@contoso.com -State Enabled + Disables MFA for john.doe@contoso.com + + .EXAMPLE + Get-MsolUser -All | Set-bdcMsolMFAState -State Disabled + Disable MFA for all users + + .EXAMPLE + (Get-MsolUser -UserPrincipalName john.doe@contoso.com | Select-Object -Property UserPrincipalName,StrongAuthenticationRequirements) + + Check the MFA state for john.doe@contoso.com + + .EXAMPLE + (Get-MsolUser -UserPrincipalName john.doe@contoso.com | Select-Object -Property UserPrincipalName,StrongAuthenticationRequirements).StrongAuthenticationRequirements + + Check the MFA details for john.doe@contoso.com + + .OUTPUTS + None + + .NOTES + Just a minor tweaked version of the original Microsoft version (See link below) + + .LINK + https://docs.microsoft.com/en-us/azure/active-directory/authentication/howto-mfa-userstates + + .INPUTS + String + #> + [CmdletBinding(ConfirmImpact = 'medium', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipelineByPropertyName)] + [string] + $ObjectId = $null, + [Parameter(ValueFromPipelineByPropertyName)] + [string] + $UserPrincipalName = $null, + [ValidateSet('Disabled', 'Enabled', 'Enforced')] + [string] + $State = 'Disabled' + ) + + begin + { + # Load the Assembly + $null = (Add-Type -AssemblyName Microsoft.Online.Administration.Automation.PSModule) + } + + process + { + Write-Verbose -Message ('Setting MFA state for user ' + $UserPrincipalName + ' (' + $ObjectId + ') to ' + $State) + + # Create a new Object + $Requirements = @() + + # Create the settings and add them to the new object + if ($State -ne 'Disabled') + { + $Requirement = [Microsoft.Online.Administration.StrongAuthenticationRequirement]::new() + $Requirement.RelyingParty = '*' + $Requirement.State = $State + $Requirements += $Requirement + } + + # Apply the new settings, based on the Object + $null = (Set-MsolUser -ObjectId $ObjectId -UserPrincipalName $UserPrincipalName -StrongAuthenticationRequirements $Requirements) + } + + end + { + # Cleanup + $Requirements = $null + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office365/TweakSafeLinksPolicy.ps1 b/Powershell/PowerShell-collection/Office365/TweakSafeLinksPolicy.ps1 new file mode 100644 index 0000000..48db202 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/TweakSafeLinksPolicy.ps1 @@ -0,0 +1,56 @@ +# Get your active SafeLinks Policy/Policies +Get-SafeLinksPolicy | Where-Object -FilterScript { + $_.IsEnabled -eq $true +} | Select-Object -ExpandProperty Identity + +# I use the default policy in this example +$SafeLinksPolicyIdentity = 'Recommended safe links policy' + +# A list of URLs to exclude from rewriting +$DoNotRewriteUrls = @( + '*.webex.com/*' + '*.zoom.us/*' + 'zoom.us/*' + '*.teams.microsoft.com/*' + 'zoom.com/*' + '*.zoom.com/*' + 'teams.microsoft.com/*' +) + +# I use the default policy in this example +Set-SafeLinksPolicy -Identity $SafeLinksPolicyIdentity -DoNotRewriteUrls $DoNotRewriteUrls +<# + Note: + The WhiteListedUrls and ExcludedUrls parameters are deprecated + Only use the DoNotRewriteUrls parameter +#> + +# Remove all URLs from the SafeLinks Policy/Policies +$DoNotRewriteUrls = @() +Set-SafeLinksPolicy -Identity $SafeLinksPolicyIdentity -DoNotRewriteUrls $DoNotRewriteUrls + +# Apply my recommended settings to the policy/policies +$paramSetSafeLinksPolicy = @{ + Identity = $SafeLinksPolicyIdentity + DoNotTrackUserClicks = $false + DoNotAllowClickThrough = $true + ScanUrls = $true + EnableForInternalSenders = $true + DeliverMessageAfterScan = $true +} +Set-SafeLinksPolicy @paramSetSafeLinksPolicy + +<# + Identity = The Identity parameter specifies the Safe Links policy that you want to modify + DoNotTrackUserClicks = Track user clicks related to links in email messages and Microsoft Teams + DoNotAllowClickThrough = Disallow users to click through to the original URL + ScanUrls = Enable real-time scanning of links in email messages + EnableForInternalSenders = The policy is applied to internal and external senders + DeliverMessageAfterScan = Wait until Safe Links scanning is complete before delivering the message +#> + +# This is fine, no panic: +# WARNING: The command completed successfully but no settings of 'Recommended safe links policy' have been modified. + +# Do this for all your Teams Room Devices that should except external invitations +Set-CalendarProcessing -Identity '' -ProcessExternalMeetingMessages $true diff --git a/Powershell/PowerShell-collection/Office365/bootstrap-Office365Tenant.ps1 b/Powershell/PowerShell-collection/Office365/bootstrap-Office365Tenant.ps1 new file mode 100644 index 0000000..739d646 --- /dev/null +++ b/Powershell/PowerShell-collection/Office365/bootstrap-Office365Tenant.ps1 @@ -0,0 +1,977 @@ +#requires -Version 2.0 + +<# + .SYNOPSIS + Bootstrap a Office 365 Tenant + + .DESCRIPTION + Bootstrap a Office 365 Tenant + It Applies some of the enabling Technology best practice settings, mostly related to security and Exchange Online. + + .NOTES + Please Review all the settings carefully before your run the script! + + You must have a connection to the following Office 365 services: + - Skype for Business Online + - Exchange Online + - Security and Compliance Center + - AzureAD (Regular Module or Preview) + + All features should work with your default Office 365 Enterprise plan. Business plans are not tested! + + PLEASE NOTE: + This is really just a basic setup. It does NOT replace an security advice by a security consultant! + + It should elevate your Security score a bit. But you still need to configure a bit more (manually or by other scripts)! + + .LINK + https://hochwald.net/office-365-minimum-security-baseline/ + + .LINK + http://www.enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + # Variables + [string[]]$AdminMail = 'support@contoso.com' + [string]$EmailCulture = 'en-US' + + #region Defaults + [string]$SCT = 'SilentlyContinue' + [string]$STP = 'Stop' + #endregion Defaults +} + +process +{ + #region + # Enable Unified audit log + $paramGetAdminAuditLogConfig = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-AdminAuditLogConfig @paramGetAdminAuditLogConfig) | Select-Object -ExpandProperty UnifiedAuditLogIngestionEnabled) -ne $true) + { + try + { + $paramSetAdminAuditLogConfig = @{ + UnifiedAuditLogIngestionEnabled = $true + ErrorAction = $SCT + WarningAction = $STP + } + $null = (Set-AdminAuditLogConfig @paramSetAdminAuditLogConfig) + Write-Output -InputObject 'Unified audit log is enabled' + } + catch + { + Write-Warning -Message 'Unable to enable Unified audit log' + } + } + else + { + Write-Output -InputObject 'Unified audit log is already enabled' + } + + $paramGetAdminAuditLogConfig = $null + $paramSetAdminAuditLogConfig = $null + #endregion + + #region + # Enable Admin audit log + $paramGetAdminAuditLogConfig = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-AdminAuditLogConfig @paramGetAdminAuditLogConfig) | Select-Object -ExpandProperty AdminAuditLogEnabled) -ne $true) + { + try + { + $paramSetAdminAuditLogConfig = @{ + AdminAuditLogEnabled = $true + AdminAuditLogCmdlets = '*' + AdminAuditLogParameters = '*' + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Set-AdminAuditLogConfig @paramSetAdminAuditLogConfig) + Write-Output -InputObject 'Admin audit log enabled' + } + catch + { + Write-Warning -Message 'Unable to enable Admin audit log' + } + } + else + { + Write-Output -InputObject 'Admin audit log is already enabled' + } + + $paramGetAdminAuditLogConfig = $null + $paramSetAdminAuditLogConfig = $null + #endregion + + #region + # Enable Mailbox Audit Logging for all mailboxes + $paramGetOrganizationConfig = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-OrganizationConfig @paramGetOrganizationConfig) | Select-Object -ExpandProperty AuditDisabled) -ne $false) + { + try + { + $paramSetOrganizationConfig = @{ + AuditDisabled = $false + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Set-OrganizationConfig @paramSetOrganizationConfig) + Write-Output -InputObject 'Mailbox Audit Logging enabled' + } + catch + { + Write-Warning -Message 'Unable to enable Mailbox Audit Logging' + } + } + else + { + Write-Output -InputObject 'Mailbox Audit Logging was already enabled' + } + + $paramGetOrganizationConfig = $null + $paramSetOrganizationConfig = $null + #endregion + + #region + # Block sign-in for all Shared, Room, and Equipment Mailboxes + <# + PLEASE NOTE: + If you use a resource like an Microsoft Teams Rooms, or a Surface Hub you might need to re-enable them afterwards! + Otherwise, your resource might not work as expected. + + The same applies to multi-factor authentication (MFA)! You will need to exclude devices like this! + #> + $paramGetMailbox = @{ + ResultSize = 'unlimited' + RecipientTypeDetails = 'SharedMailbox', 'RoomMailbox', 'EquipmentMailbox' + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-Mailbox @paramGetMailbox | Select-Object -ExpandProperty UserPrincipalName | ForEach-Object { + $paramSetAzureAdUser = @{ + ObjectId = $_ + AccountEnabled = $false + ErrorAction = $SCT + WarningAction = $SCT + } + Set-AzureADUser @paramSetAzureAdUser + }) + #endregion + + #region + # Apply and activate for each Mailbox + try + { + $paramGetMailbox = @{ + ResultSize = 'Unlimited' + ErrorAction = $SCT + WarningAction = $SCT + } + $null = ((Get-Mailbox @paramGetMailbox) | Where-Object -FilterScript { + ($_.RecipientTypeDetails -ne 'DiscoveryMailbox') -and ($_.AuditEnabled -ne $true) + } | ForEach-Object -Process { + $paramSetMailbox = @{ + Identity = $_.UserPrincipalName + AuditEnabled = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Set-Mailbox @paramSetMailbox) + }) + Write-Output -InputObject 'Applied and activated audit for each Mailbox' + } + catch + { + Write-Warning -Message 'Unable to apply and/or activate audit for each Mailbox' + } + finally + { + $paramGetMailbox = $null + $paramSetMailbox = $null + } + #endregion + + #region + # Disable POP3/IMAP4 + try + { + $paramGetCASMailboxPlan = @{ + Filter = { + ImapEnabled -eq 'true' -or PopEnabled -eq 'true' + } + ErrorAction = $SCT + WarningAction = $SCT + } + $paramSetCASMailboxPlan = @{ + ImapEnabled = $false + PopEnabled = $false + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Get-CASMailboxPlan @paramGetCASMailboxPlan | set-CASMailboxPlan @paramSetCASMailboxPlan) + Write-Output -InputObject 'POP3 and IMAP4 are disabled - CAS Mailbox Plan' + } + catch + { + Write-Warning -Message 'Unable to disable POP3 and IMAP4 - CAS Mailbox Plan' + } + finally + { + $paramGetCASMailboxPlan = $null + $paramSetCASMailboxPlan = $null + } + + try + { + $paramGetCASMailbox = @{ + Filter = { + ImapEnabled -eq 'true' -or PopEnabled -eq 'true' + } + ErrorAction = $SCT + WarningAction = $SCT + } + $paramSetCASMailbox = @{ + ImapEnabled = $false + PopEnabled = $false + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Get-CASMailbox @paramGetCASMailbox | Select-Object -Property @{ + Name = 'Identity' + Expression = { + $_.PrimarySmtpAddress + } + } | Set-CASMailbox @paramSetCASMailbox) + Write-Output -InputObject 'POP3 and IMAP4 are disabled - CAS Mailbox' + } + catch + { + Write-Warning -Message 'Unable to disable POP3 and IMAP4 - CAS Mailbox' + } + finally + { + $paramGetCASMailbox = $null + $paramSetCASMailbox = $null + } + #endregion + + #region + # Enable/Set End User Spam Notification + try + { + $ExistingHostedContentFilterPolicy = (Get-HostedContentFilterPolicy -Identity Default -ErrorAction $SCT -WarningAction $SCT | Select-Object -Property EndUserSpamNotificationFrequency, HighConfidenceSpamAction, EnableEndUserSpamNotifications) + + if ((-not ($ExistingHostedContentFilterPolicy.EndUserSpamNotificationFrequency -eq 1)) -and (-not ($ExistingHostedContentFilterPolicy.HighConfidenceSpamAction -eq 'HighConfidenceSpamAction')) -and (-not ($ExistingHostedContentFilterPolicy.EnableEndUserSpamNotifications -eq $true))) + { + $paramSetHostedContentFilterPolicy = @{ + Identity = 'Default' + EndUserSpamNotificationFrequency = 1 + EndUserSpamNotificationLanguage = 'Default' + HighConfidenceSpamAction = 'Quarantine' + EnableEndUserSpamNotifications = $true + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Set-HostedContentFilterPolicy @paramSetHostedContentFilterPolicy) + Write-Output -InputObject 'Hosted Content Filter Policy was fixed' + } + else + { + Write-Output -InputObject 'Hosted Content Filter Policy was not fixed' + } + } + catch + { + Write-Warning -Message 'Unable to fix Hosted Content Filter Policy' + } + finally + { + $ExistingHostedContentFilterPolicy = $null + $paramSetHostedContentFilterPolicy = $null + } + #endregion + + #region + # Enable/Set Outbound Spam Filter Notification + try + { + $ExistingHostedOutboundSpamFilterPolicy = (Get-HostedOutboundSpamFilterPolicy -Identity Default -ErrorAction $SCT -WarningAction $SCT | Select-Object -Property NotifyOutboundSpamRecipients, NotifyOutboundSpam) + + if ((-not ($ExistingHostedOutboundSpamFilterPolicy.NotifyOutboundSpamRecipients -eq $AdminMail)) -and (-not ($ExistingHostedOutboundSpamFilterPolicy.NotifyOutboundSpam -eq $true))) + { + $paramSetHostedOutboundSpamFilterPolicy = @{ + Identity = 'Default' + NotifyOutboundSpamRecipients = $AdminMail + NotifyOutboundSpam = $true + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Set-HostedOutboundSpamFilterPolicy @paramSetHostedOutboundSpamFilterPolicy) + Write-Output -InputObject 'Hosted Outbound Spam Filter Policy was fixed' + } + else + { + Write-Output -InputObject 'Hosted Outbound Spam Filter Policy was not fixed' + } + } + catch + { + Write-Warning -Message 'Unable to fix the Hosted Outbound Spam Filter Policy' + } + finally + { + $ExistingHostedOutboundSpamFilterPolicy = $null + $paramSetHostedOutboundSpamFilterPolicy = $null + } + #endregion + + #region + # Deploying minimum baseline MobileDeviceMailboxPolicy + $paramGetMobileDeviceMailboxPolicy = @{ + Identity = 'Default' + ErrorAction = $SCT + WarningAction = $SCT + } + $DefaultMobileDeviceMailboxPolicy = (Get-MobileDeviceMailboxPolicy @paramGetMobileDeviceMailboxPolicy | Select-Object -Property PasswordEnabled, AllowSimplePassword, AlphanumericPasswordRequired, MinPasswordLength, RequireDeviceEncryption, AllowNonProvisionableDevices) + #endregion + + #region + # Check existing settings + if (($DefaultMobileDeviceMailboxPolicy.PasswordEnabled -eq $true) -and (($DefaultMobileDeviceMailboxPolicy.AllowSimplePassword -eq $true) -or ($DefaultMobileDeviceMailboxPolicy.AlphanumericPasswordRequired -eq $true)) -and ($DefaultMobileDeviceMailboxPolicy.MinPasswordLength -ge 4) -and ($DefaultMobileDeviceMailboxPolicy.RequireDeviceEncryption -eq $true) -and ($DefaultMobileDeviceMailboxPolicy.AllowNonProvisionableDevices -eq $false)) + { + Write-Output -InputObject 'Minimum, or better, baseline MobileDeviceMailboxPolicy already applied' + } + else + { + try + { + $paramSetMobileDeviceMailboxPolicy = @{ + Identity = 'Default' + PasswordEnabled = $true + AllowSimplePassword = $true + MinPasswordLength = 4 + RequireDeviceEncryption = $true + AllowNonProvisionableDevices = $false + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Set-MobileDeviceMailboxPolicy @paramSetMobileDeviceMailboxPolicy) + Write-Output -InputObject 'Minimum baseline MobileDeviceMailboxPolicy applied' + } + catch + { + Write-Warning -Message 'Unable to change and/or apply the Minimum baseline MobileDeviceMailboxPolicy' + } + } + + $paramGetMobileDeviceMailboxPolicy = $null + $DefaultMobileDeviceMailboxPolicy = $null + $paramSetMobileDeviceMailboxPolicy = $null + #endregion + + #region + # Enable general Modern Authentication + <# + PLEASE NOTE: + Microsoft Teams Rooms does NOT support Modern Authentication yet! (At least not with version 4.3.42.0 from 03/02/2019) + If you have a device like the Microsoft Teams Rooms, you might not be able to disable legacy Auth (basic authentication). + This will break the function and your device will no longer be able to authenticate. + + Please check for the latest release notes: + https://docs.microsoft.com/en-us/MicrosoftTeams/rooms/rooms-release-note + #> + $paramGetOrganizationConfig = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-OrganizationConfig @paramGetOrganizationConfig) | Select-Object -ExpandProperty OAuth2ClientProfileEnabled) -ne $true) + { + try + { + $paramSetOrganizationConfig = @{ + OAuth2ClientProfileEnabled = $true + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Set-OrganizationConfig @paramSetOrganizationConfig) + Write-Output -InputObject 'Modern Authentication is enabled' + } + catch + { + Write-Warning -Message 'Unable to enable Modern Authentication' + } + } + else + { + Write-Output -InputObject 'Modern Authentication is already enabled' + } + + $paramGetOrganizationConfig = $null + $paramSetOrganizationConfig = $null + #endregion + + #region + # Enable Modern Authentication in Skype for Business Online + $paramGetCsOAuthConfiguration = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-CsOAuthConfiguration @paramGetCsOAuthConfiguration) | Select-Object -ExpandProperty ClientAdalAuthOverride) -ne 'Allowed') + { + try + { + $paramSetCsOAuthConfiguration = @{ + ClientAdalAuthOverride = 'Allowed' + ErrorAction = $STP + WarningAction = $SCT + } + $null = (Set-CsOAuthConfiguration @paramSetCsOAuthConfiguration) + Write-Output -InputObject 'Modern Authentication was enabled for Skype for Business Online' + } + catch + { + Write-Warning -Message 'Unable to enable Modern Authentication for Skype for Business Online' + } + } + else + { + Write-Output -InputObject 'Modern Authentication is already enabled for Skype for Business Online' + } + + $paramGetCsOAuthConfiguration = $null + $paramSetCsOAuthConfiguration = $null + #endregion + + #region + # Block forwarding mail externally + $BlockForwardingRuleName = 'Block forwarding mail externally' + + $paramGetTransportRule = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-TransportRule @paramGetTransportRule | Where-Object -FilterScript { + $_.Name -eq $BlockForwardingRuleName + })) + { + try + { + $paramNewTransportRule = @{ + Name = $BlockForwardingRuleName + Priority = 1 + SentToScope = 'NotInOrganization' + FromScope = 'InOrganization' + SenderAddressLocation = 'HeaderOrEnvelope' + MessageTypeMatches = 'AutoForward' + RejectMessageEnhancedStatusCode = '5.7.1' + RejectMessageReasonText = ('To improve security, auto-forwarding rules to external addresses has been disabled. Please contact ' + $AdminMail + " if you'd like to set up an exception.") + Mode = 'Audit' + Comments = 'Block forwarding mail externally' + ErrorAction = $STP + WarningAction = $SCT + } + $null = (New-TransportRule @paramNewTransportRule) + Write-Output -InputObject 'Block auto-forwarding rules to external addresses was created' + } + catch + { + Write-Warning -Message 'Block auto-forwarding rules to external addresses was not created' + } + } + else + { + Write-Output -InputObject 'Block auto-forwarding rules to external addresses already exists' + } + + $BlockForwardingRuleName = $null + $paramGetTransportRule = $null + $paramNewTransportRule = $null + #endregion + + #region + # Warn users if inbound external mail with display name matching internal users + $ExternalSenderWithInternalDisplayNameRuleName = 'External Senders with matching Display Names' + + $paramGetTransportRule = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-TransportRule @paramGetTransportRule | Where-Object -FilterScript { + $_.Name -eq $ExternalSenderWithInternalDisplayNameRuleName + })) + { + try + { + # Please review! This text will be displayed to your users!!! + $ApplyHtmlDisclaimerText = "

CAUTION: This email originated from outside of the organization by someone with a display name matching a user in your organization. Please do not click links or open attachments unless you recognize the source of this email and know the content is safe.

 

" + + $paramNewTransportRule = @{ + Name = $ExternalSenderWithInternalDisplayNameRuleName + Priority = 2 + FromScope = 'NotInOrganization' + SenderAddressLocation = 'HeaderOrEnvelope' + ApplyHtmlDisclaimerLocation = 'Prepend' + HeaderMatchesMessageHeader = 'From' + HeaderMatchesPatterns = ((Get-Mailbox -ResultSize Unlimited -RecipientTypeDetails UserMailbox, SharedMailbox) | Select-Object -ExpandProperty DisplayName) + ApplyHtmlDisclaimerText = $ApplyHtmlDisclaimerText + ApplyHtmlDisclaimerFallbackAction = 'Wrap' + SetHeaderName = 'X-bdcRule' + SetHeaderValue = $ExternalSenderWithInternalDisplayNameRuleName + ErrorAction = $STP + WarningAction = $SCT + } + $null = (New-TransportRule @paramNewTransportRule) + Write-Output -InputObject 'External Sender with internal Display Name Rule was created' + } + catch + { + Write-Warning -Message 'External Sender with internal Display Name Rule was not created' + } + } + else + { + Write-Output -InputObject 'External Sender with internal Display Name Rule already exists' + } + + $ExternalSenderWithInternalDisplayNameRuleName = $null + $ApplyHtmlDisclaimerText = $null + $paramGetTransportRule = $null + $paramNewTransportRule = $null + #endregion + + #region + # Mark all external Messages + $MarkExternalMessagesRuleName = 'Mark external Messages' + + $paramGetTransportRule = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-TransportRule @paramGetTransportRule | Where-Object -FilterScript { + $_.Name -eq $MarkExternalMessagesRuleName + })) + { + try + { + # Please review! This text will be displayed to your users!!! + $ApplyHtmlDisclaimerText = "

CAUTION: This email originated from outside of the organization. Please do not click links or open attachments unless you recognize the source of this email and know the content is safe.

 

" + + $paramNewTransportRule = @{ + Name = $MarkExternalMessagesRuleName + Priority = 3 + FromScope = 'NotInOrganization' + SenderAddressLocation = 'HeaderOrEnvelope' + ApplyHtmlDisclaimerLocation = 'Prepend' + ApplyHtmlDisclaimerText = $ApplyHtmlDisclaimerText + ApplyHtmlDisclaimerFallbackAction = 'Wrap' + SetHeaderName = 'X-bdcRule' + SetHeaderValue = $MarkExternalMessagesRuleName + ErrorAction = $STP + WarningAction = $SCT + } + $null = (New-TransportRule @paramNewTransportRule) + Write-Output -InputObject 'Mark External Messages Rule was created' + } + catch + { + Write-Warning -Message 'Mark External Messages Rule was not created' + } + } + else + { + Write-Output -InputObject 'Mark External Messages Rule already exists' + } + + $MarkExternalMessagesRuleName = $null + $ApplyHtmlDisclaimerText = $null + $paramGetTransportRule = $null + $paramNewTransportRule = $null + #endregion + + #region + # See the Description field, that will explain what each alter will do. + try + { + $paramNewActivityAlert = @{ + Name = 'File and Page Alert' + Operation = 'Filemalwaredetected' + NotifyUser = $AdminMail + UserId = $null + Description = 'SharePoint anti-virus engine detects malware in a file.' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'High' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Anonymous Links Alert' + Operation = 'Anonymouslinkcreated', 'Anonymouslinkupdated', 'Anonymouslinkused' + NotifyUser = $AdminMail + UserId = $null + Description = 'User created an anonymous link to a resource. User updated an anonymous link to a resource. An anonymous user accessed a resource by using an anonymous link.' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'Medium' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Sharing Alert' + Operation = 'Sharinginvitationcreated', 'Sharingpolicychanged' + NotifyUser = $AdminMail + UserId = $null + Description = "User shared a resource in SharePoint Online or OneDrive for Business with a user who isn't in your organization's directory. A SharePoint or global administrator changed a SharePoint sharing policy." + ErrorAction = $STP + WarningAction = $SCT + Severity = 'None' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Access Alert' + Operation = 'Deviceaccesspolicychanged', 'Networkaccesspolicychanged' + NotifyUser = $AdminMail + UserId = $null + Description = 'Change in the unmanaged devices policy.Change in the location-based access policy (also called a trusted network boundary).' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'Medium' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Site Alert' + Operation = 'Sitecollectioncreated', 'Sitedeleted', 'Sitecollectionadminadded' + NotifyUser = $AdminMail + UserId = $null + Description = 'Creation of a new site collection OneDrive for Business site provisioned. A site was deleted.Site collection administrator or owner adds a person as a site collection administrator for a site.' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'None' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Office Alert' + Operation = 'Officeondemandset' + NotifyUser = $AdminMail + UserId = $null + Description = 'Site administrator enables Office on Demand, which lets users access the latest version of Office desktop applications.' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'None' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Mailbox Alert' + Operation = 'Add-mailboxpermission', 'Remove-mailboxpermission' + NotifyUser = $AdminMail + UserId = $null + Description = "An administrator assigned/removed the FullAccess mailbox permission to a user (known as a delegate) to another person`'s mailbox" + ErrorAction = $STP + WarningAction = $SCT + Severity = 'None' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Password Alert' + Operation = 'Change user password.', 'Reset user password.', 'Set force change user password.' + NotifyUser = $AdminMail + UserId = $null + Description = 'User password changes' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'None' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Role Alert' + Operation = 'Add member to role.', 'Remove member from role.' + NotifyUser = $AdminMail + UserId = $null + Description = 'Added/Removed a user to an admin role in Office 365.' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'Medium' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Company Information Alert' + Operation = 'Set company contact information.', 'Set company information.', 'Set password policy.', 'Remove partner from company.' + NotifyUser = $AdminMail + UserId = $null + Description = 'Change company information or password policy' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'High' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + + try + { + $paramNewActivityAlert = @{ + Name = 'Domain Alert' + Operation = 'Add domain to company.', 'Remove domain from company.', 'Update domain.' + NotifyUser = $AdminMail + UserId = $null + Description = 'Change of a custom domain in a tenant' + ErrorAction = $STP + WarningAction = $SCT + Severity = 'High' + EmailCulture = $EmailCulture + Disabled = $false + } + if (-not (Get-ActivityAlert -Name $paramNewActivityAlert.Name -ErrorAction $SCT)) + { + $null = (New-ActivityAlert @paramNewActivityAlert) + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was created') + } + else + { + Write-Output -InputObject ('The ' + $paramNewActivityAlert.Name + ' Activity Alert exists') + } + } + catch + { + Write-Warning -Message ('The ' + $paramNewActivityAlert.Name + ' Activity Alert was not created') + } + + $paramNewActivityAlert = $null + #endregion +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office_Related/Force_Office_Click2Run-Update.ps1 b/Powershell/PowerShell-collection/Office_Related/Force_Office_Click2Run-Update.ps1 new file mode 100644 index 0000000..d3e0038 --- /dev/null +++ b/Powershell/PowerShell-collection/Office_Related/Force_Office_Click2Run-Update.ps1 @@ -0,0 +1,83 @@ +#requires -Version 2.0 + +<# + .SYNOPSIS + Triggers the Click 2 Run Update Process + + .DESCRIPTION + This Script triggers the Click 2 Run Update Process. + + .PARAMETER Silent + Suppress the User Info + + .EXAMPLE + # Regular Operation + PS C:\> .\Force_Office_Click2Run-Update.ps1 + + .EXAMPLE + # Silent Operation + PS C:\> .\Force_Office_Click2Run-Update.ps1 -Silent + + .EXAMPLE + # Silent Operation + PS C:\> .\Force_Office_Click2Run-Update.ps1 -s + + .NOTES + Author: Joerg Hochwald - http://hochwald.net + License: Freeware, Public Domain +#> +param +( + [Parameter(ValueFromPipeline = $true, + Position = 1)] + [Alias('s')] + [switch] + $Silent +) + +begin +{ + # Constants + $SC = 'SilentlyContinue' + + # The Click 2 Run Executable + $UpdateEXE = "$env:CommonProgramW6432\Microsoft Shared\ClickToRun\OfficeC2RClient.exe" + + if ($Silent) + { + # Commandline (Silent) + $UpdateArguements = '/update user displaylevel=false' + } + else + { + # Commandline (Inform the User in this case) + $UpdateArguements = '/update user displaylevel=true' + } +} +process +{ + $paramTestPath = @{ + Path = $UpdateEXE + ErrorAction = $SC + } + if (Test-Path @paramTestPath) + { + try + { + $paramStartProcess = @{ + FilePath = $UpdateEXE + ArgumentList = $UpdateArguements + ErrorAction = $SC + } + $null = (Start-Process @paramStartProcess) + } + catch + { + Write-Warning -Message 'Unable to start the Update Process...' + } + } + else + { + Write-Error -Message 'The Office Click 2 Run Update executable was not found!' -ErrorAction Stop + } +} diff --git a/Powershell/PowerShell-collection/Office_Related/LICENSE b/Powershell/PowerShell-collection/Office_Related/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Office_Related/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Office_Related/README.md b/Powershell/PowerShell-collection/Office_Related/README.md new file mode 100644 index 0000000..d7338b1 --- /dev/null +++ b/Powershell/PowerShell-collection/Office_Related/README.md @@ -0,0 +1,8 @@ +# Legacy Notice + +I no longer run Exchange, Skype for Business, or any other Office Server on Premises. +This is my personal [reaction](https://hochwald.net/microsoft-rolls-back-decision-to-take-away-internal-usage-rights-from-partners/) to the changes that Microsoft [announced](https://hochwald.net/microsoft-is-going-to-kill-internal-use-rights-benefit-for-partners/) for the Internal Use Rights (IUR) program. I know that they decided to reverse that changes and in theory, I could still legally use the software. However, I decided to decommission everything licensed under the terms of the Internal Use Rights (IUR) program. +In my opinion, the community always should have some benefits from the Internal Use Rights (IUR) program and/or Action Pack. Now that I decided to drop out, there will be no more such benefits. + +I will _no longer maintain_ the scripts related to the Microsoft Office (on Premises) servers. They will remain here, but unmaintained. Fork the repository and maintain or extend them if you like to. The [License](https://github.com/jhochwald/PowerShell-collection/blob/master/LICENSE) allows that easily. + diff --git a/Powershell/PowerShell-collection/Office_Related/Set-OfficeInsider.ps1 b/Powershell/PowerShell-collection/Office_Related/Set-OfficeInsider.ps1 new file mode 100644 index 0000000..64efbbe --- /dev/null +++ b/Powershell/PowerShell-collection/Office_Related/Set-OfficeInsider.ps1 @@ -0,0 +1,109 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + This script will set the Office Channel info in the Registry + + .DESCRIPTION + This script will add the Office Insider Channel Information in the Registry. + It is a Quick and Dirty Solution. + + .PARAMETER Channel + The Office Release Channel + + Possible Values for the Channel Variable are: + Insiderfast - With weekly builds, not generally supported + FirstReleaseCurrent - Office Insider Slow aka First Release Channel + Current - Current Channel (Default) + Validation - First Release for Deferred Channel + Business - Also known as Current Branch for Business + + .EXAMPLE + # Set the Distribution Channel to Insiderfast - Weekly builds + PS> .\Set-OfficeInsider.ps1 -Channel 'Insiderfast' + + .EXAMPLE + # Set the Distribution Channel to Business - Slow updates + PS> .\Set-OfficeInsider.ps1 -Channel 'Business' + + .NOTES + This will work with Windows based Office 365 (Click to Run) installations only! + + Change the Release Channel might cause issues! Do this at your own risk. + Not all Channels are supported by Microsoft. + + Author: Joerg Hochwald - http://hochwald.net +#> +param +( + [Parameter(ValueFromPipeline = $true, + Position = 1)] + [ValidateSet('Insiderfast', 'FirstReleaseCurrent', 'Current', 'Validation', 'Business', IgnoreCase = $true)] + [ValidateNotNullOrEmpty()] + [string] + $Channel = 'Current' +) + +begin +{ + # Constants + $SC = 'SilentlyContinue' + + try + { + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\office\16.0\common\' + Name = 'officeupdate' + Force = $true + ErrorAction = $SC + WarningAction = $SC + Confirm = $false + } + $null = (New-Item @paramNewItem) + + Write-Verbose -Message 'The Registry Structure was created.' + } + catch + { + Write-Verbose -Message 'The Registry Structure exists...' + } +} + +process +{ + try + { + $paramNewItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\office\16.0\common\officeupdate' + Name = 'updatebranch' + PropertyType = 'String' + Value = $Channel + Force = $true + ErrorAction = $SC + WarningAction = $SC + Confirm = $false + } + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message 'Registry Entry was created.' + } + catch + { + $paramSetItem = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\office\16.0\common\officeupdate\updatebranch' + Value = $Channel + Force = $true + ErrorAction = $SC + WarningAction = $SC + Confirm = $false + } + $null = (Set-Item @paramSetItem) + + Write-Verbose -Message 'Registry Entry was changed.' + } +} + +end +{ + Write-Output -InputObject "Office Release Channel Set to $Channel" +} diff --git a/Powershell/PowerShell-collection/Office_Related/Set-PreventBingInstallRegistryKey.ps1 b/Powershell/PowerShell-collection/Office_Related/Set-PreventBingInstallRegistryKey.ps1 new file mode 100644 index 0000000..a067c31 --- /dev/null +++ b/Powershell/PowerShell-collection/Office_Related/Set-PreventBingInstallRegistryKey.ps1 @@ -0,0 +1,96 @@ +<# + .SYNOPSIS + Prevent the installation of Bing Search extension in Chrome by tweak the registry + + .DESCRIPTION + Microsoft will install a Bing Search extension in Chrome with Office 365 ProPlus, this script prevents this. + + .EXAMPLE + PS C:\> .\Set-PreventBingInstallRegistryKey.ps1 + + Prevent the installation of Bing Search extension in Chrome by tweak the registry + + .NOTES + If you have a fully Domain managed Client, of the client is managed by Azure AD/Intune, you can handle this there. + If not (remote users?), you might want to tweak your Registry to prevent the installation of the Bing Search extension in Chrome + This script will create the matching registry value, if the registry entry exists it also ensures that it is set to prevent the installation. + + .LINK + https://docs.microsoft.com/en-us/deployoffice/microsoft-search-bing#how-to-exclude-the-extension-for-microsoft-search-in-bing-from-being-installed + + .LINK + https://github.com/MicrosoftDocs/OfficeDocs-DeployOffice/issues/659 + + .LINK + https://o365reports.com/2020/01/22/using-office-365-proplus-chrome-youll-soon-be-binged/ +#> +[CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess = $true)] +param () + +begin +{ + #region Defaults + $RegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Office\16.0\Common\Officeupdate' + $RegistryName = 'preventbinginstall' + $RegistryValue = '00000001' + #endregion Defaults +} + +process +{ + if (-not (Test-Path -Path $RegistryPath -ErrorAction SilentlyContinue)) + { + #region CompareValue + <# + Compare to ensure that we have the correct settings + We compressed this a bit to make this one (long) line! + #> + if (((Get-Item -LiteralPath $RegistryPath -ErrorAction SilentlyContinue).GetValue($RegistryName, $null)) -ne ($RegistryValue.Replace('0', ''))) + { + # Enforce the value to be what we want + $null = (Set-ItemProperty -Path $RegistryPath -Name $RegistryName -Value $RegistryValue -Force -ErrorAction SilentlyContinue -Confirm:$false) + } + #endregion CompareValue + } + else + { + #region CreateValue + # Ensure the structure exists + $null = (New-Item -Path $RegistryPath -Force -ErrorAction SilentlyContinue -Confirm:$false -ItemType 'directory') + + # Set the registry key to the correct value + $null = (New-ItemProperty -Path $RegistryPath -Name $RegistryName -Value $RegistryValue -PropertyType DWORD -Force -ErrorAction SilentlyContinue -Confirm:$false) + #endregion CreateValue + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Office_Related/Set-PreventBingInstallRegistryKey_splat.ps1 b/Powershell/PowerShell-collection/Office_Related/Set-PreventBingInstallRegistryKey_splat.ps1 new file mode 100644 index 0000000..e526eea --- /dev/null +++ b/Powershell/PowerShell-collection/Office_Related/Set-PreventBingInstallRegistryKey_splat.ps1 @@ -0,0 +1,130 @@ +<# + .SYNOPSIS + Prevent the installation of Bing Search extension in Chrome by tweak the registry + + .DESCRIPTION + Microsoft will install a Bing Search extension in Chrome with Office 365 ProPlus, this script prevents this. + + .EXAMPLE + PS C:\> .\Set-PreventBingInstallRegistryKey_splat.ps1 + + Prevent the installation of Bing Search extension in Chrome by tweak the registry + + .NOTES + In this version all commands are splatted to make it better readable (e.g. no long lines) + + If you have a fully Domain managed Client, of the client is managed by Azure AD/Intune, you can handle this there. + If not (remote users?), you might want to tweak your Registry to prevent the installation of the Bing Search extension in Chrome + This script will create the matching registry value, if the registry entry exists it also ensures that it is set to prevent the installation. + + .LINK + https://docs.microsoft.com/en-us/deployoffice/microsoft-search-bing#how-to-exclude-the-extension-for-microsoft-search-in-bing-from-being-installed + + .LINK + https://github.com/MicrosoftDocs/OfficeDocs-DeployOffice/issues/659 + + .LINK + https://o365reports.com/2020/01/22/using-office-365-proplus-chrome-youll-soon-be-binged/ +#> +[CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess = $true)] +param () + +begin +{ + #region Defaults + $RegistryPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Office\16.0\Common\Officeupdate' + $RegistryName = 'preventbinginstall' + $RegistryValue = '00000001' + #endregion Defaults +} + +process +{ + $paramTestPath = @{ + Path = $RegistryPath + ErrorAction = 'SilentlyContinue' + } + if (-not (Test-Path @paramTestPath)) + { + #region CompareValue + <# + Compare to ensure that we have the correct settings + We compressed this a bit to make this one (long) line! + #> + $paramGetItem = @{ + LiteralPath = $RegistryPath + ErrorAction = 'SilentlyContinue' + } + if (((Get-Item @paramGetItem ).GetValue($RegistryName, $null)) -ne ($RegistryValue.Replace('0', ''))) + { + # Enforce the value to be what we want + $paramSetItemProperty = @{ + Path = $RegistryPath + Name = $RegistryName + Value = $RegistryValue + Force = $true + ErrorAction = 'SilentlyContinue' + Confirm = $false + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + #endregion CompareValue + } + else + { + #region CreateValue + # Ensure the structure exists + $paramNewItem = @{ + Path = $RegistryPath + Force = $true + ErrorAction = 'SilentlyContinue' + Confirm = $false + ItemType = 'directory' + } + $null = (New-Item @paramNewItem) + + # Set the registry key to the correct value + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = $RegistryName + Value = $RegistryValue + PropertyType = 'DWORD' + Force = $true + ErrorAction = 'SilentlyContinue' + Confirm = $false + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion CreateValue + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Skype_for_Business/Collect-CsClientLogs.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/Collect-CsClientLogs.ps1 new file mode 100644 index 0000000..6b83a40 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/Collect-CsClientLogs.ps1 @@ -0,0 +1,172 @@ +<# + .SYNOPSIS + Allows you to collect the Lync/Skype for Business Client logs and puts them + in a Zip file on your desktop. + + .DESCRIPTION + This script identifies which version of Lync 2013 or Skype for Business 2015/2016 + client that you are using to identify where the Tracing folder is stored. Then + it checks to see if the lync.exe is running. If so, it prompts you to exit the + client so that it can zip the complete tracing folder and place it on your desktop. + + .EXAMPLE + .\Collect-CsClientLogs.ps1 + + This will collect the logs and put them on your desktop in a file named Tracing_DATETIME.zip + + .NOTES + The client tracing logs contain personally identifiable information or PII. If + you are sending these logs to someone for analysis, do not send it in any manner + that isn't encrypted with SSL or TLS. Email is not a secure way to transfer + this data. + + This script DOES NOT work with Lync 2010. Lync 2010 Client logs are in %UserProfile%\Tracing + +#> +Function getDateTimeForFileName +{ + $DT = (Get-Date) + $FileNameAddition = '_' + $FileNameAddition += ($DT.Month).ToString('00') + '-' + $FileNameAddition += ($DT.Day).ToString('00') + '-' + $FileNameAddition += ($DT.Year).ToString('0000') + '_' + $FileNameAddition += ($DT.Hour).ToString('00') + '.' + $FileNameAddition += ($DT.Minute).ToString('00') + '.' + $FileNameAddition += ($DT.Second).ToString('00') + Return $FileNameAddition +} + +# Show PII Warning +Write-Warning -Message "The client tracing logs contain personally identifiable information or PII. If you are sending these logs to someone for analysis, do not send it in any manner that isn't encrypted with SSL or TLS. Email is not a secure way to transfer this data." +$Answer = Read-Host -Prompt 'Type YES and hit [Enter] if you understand this warning' + +If (-not ($Answer -eq 'yes')) +{ + Write-Warning -Message "You did not type `"Yes`" to the above warning. Script has ended and no data has been collected" + Break +} + +# Stop Lync and Skype from Running +Write-Warning -Message 'The following programs must be closed: Outlook, and Skype for Business. Please close them now.' + +$Answer2 = Read-Host -Prompt 'Are Skype for Business and Outlook closed? YES or NO?' + +while ($Answer2 -ne 'yes') +{ + Write-Output -InputObject "Please close the programs and confirm with 'YES'" + $Answer2 = Read-Host -Prompt 'Waiting for answer: ' +} + +# Turn off the proceesses on the machine. These lines will forcibly kill the programs. +$OutlookProcess = (Get-Process -Name Outlook -ErrorVariable OutlookError -ErrorAction SilentlyContinue) +if ($OutlookProcess -ne $null) +{ + $OutlookProcess.CloseMainWindow() +} + +$LyncPS = (Get-Process -Name lync* -ErrorVariable LyncError -ErrorAction SilentlyContinue) +if ($LyncPS -ne $null) +{ + $LyncPS.CloseMainWindow() +} +# Figure out which Lync/Skype version is being used. +$OfficeInstalls = Get-ChildItem -Path hklm:\software\microsoft\windows\currentversion\uninstall | ForEach-Object -Process { + Get-ItemProperty -Path $_.pspath +} | Where-Object -FilterScript { + ($_.displayname -match 'Office') -and ($_.InstallLocation.Length -gt 1) +} +$Found = $False +ForEach ($Path in $OfficeInstalls.InstallLocation) +{ + $File = Get-ChildItem -Path $Path -Filter 'Lync.exe' -Recurse + + If ($File.Name.Length -gt 0) + { + $LyncVersion = [Diagnostics.FileVersionInfo]::GetVersionInfo($File.FullName).FileVersion + $LyncPath = $File.FullName + $Found = $true + } +} + +If ($Found) +{ + $Version = $LyncVersion.Substring(0, 4) +} + +# Set the Tracing Folder Path +$LogPath = ($env:USERPROFILE + '\AppData\Local\Microsoft\Office\' + $Version + '\Lync\Tracing') + +if (Test-Path -Path $LogPath) +{ + # Check to see if Lync.exe is running. + $LyncPID = ((Get-WmiObject -Class win32_process | Where-Object -FilterScript { + ($_.ProcessName -eq 'lync.exe') -and ($_.GetOwner().User -eq $env:USERNAME) + }).ProcessID) + $LyncProcess = (Get-Process -Id $LyncPID -ErrorAction SilentlyContinue) + + While ($LyncProcess.ProcessName.Length -ne 0) + { + # If Running Prompt to Exit Lync.exe + Write-Warning -Message 'Lync/Skype is still running' + Write-Output -InputObject 'Please Exit Lync/Skype and press Any Key to continue...' + + $null = ($Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')) + $LyncProcess = (Get-Process -Id $LyncPID -ErrorAction SilentlyContinue) + } + + # Compress entire Tracing Folder and place on Desktop (Filename with DateTimeStamp in name) + $ZipFile = 'Tracing$(getDateTimeForFilename).zip' + + Write-Output -InputObject ('Zipping Tracing folder and placing on your Desktop ({0})' -f $ZipFile) + + $null = (Add-Type -AssemblyName 'system.io.compression.filesystem') + + # Alter the destination + + [io.compression.zipfile]::CreateFromDirectory($LogPath, "$env:USERPROFILE\Desktop\$ZipFile") + + Write-Output -InputObject 'Log Collection Complete.' + Write-Output -InputObject "Press `"Y`" to Launch the Lync/Skype Client. Hit any other key to quit." + + $Answer = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown') + + If ($Answer.VirtualKeyCode -eq 89) + { + . "$LyncPath" + } +} +else +{ + Write-Output -InputObject "Cannot find Tracing folder path ($LogPath)" + Write-Output -InputObject 'This might be because you have never launched Lync or the Script detected the wrong version' + Write-Output -InputObject 'You are going to have to manually collect the logs' +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Skype_for_Business/Get-CsActiveConferences.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/Get-CsActiveConferences.ps1 new file mode 100644 index 0000000..9e1d628 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/Get-CsActiveConferences.ps1 @@ -0,0 +1,278 @@ +#requires -Version 3.0 + +<# + .SYNOPSIS + List all active Lync/Skype for Business conferences + + .DESCRIPTION + List all active Lync/Skype for Business conferences + + .PARAMETER FrontendPool + Please enter the Lync/Skype for Business Frontend Pool FQDN + + .EXAMPLE + PS C:\> .\Get-CsActiveConferences.ps1 -FrontendPool 'atl-cs-001.litwareinc.com' + + .NOTES + Originally written by Richard Brynteson + + .LINK + https://masteringlync.com/2013/11/19/list-all-active-conferences-via-powershell/ +#> +[CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] +param +( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'Please enter the Frontend Pool FQDN')] + [ValidateNotNullOrEmpty()] + [Alias('PoolFQDN')] + [string] + $FrontendPool +) + +begin +{ + # Convert UTC to Local timezone + function Convert-UTCtoLocal + { + <# + .SYNOPSIS + Convert UTC to Local timezone + + .DESCRIPTION + Convert UTC to Local timezone + + .PARAMETER UTCTime + UTC Time Format datetime + + .EXAMPLE + PS C:\> Convert-UTCtoLocal -UTCTime Value + Convert UTC to Local timezone + + .OUTPUTS + datetime + + .INPUTS + datetime + + .NOTES + Just a small internal Helper Script + #> + + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([datetime])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1, + HelpMessage = 'UTC Time Format datetime')] + [ValidateNotNullOrEmpty()] + [datetime] + $UTCTime + ) + + begin + { + # Cleanup + $LocalTime = $null + } + + process + { + # Transform the Format + $paramGetWmiObject = @{ + Class = 'win32_timezone' + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $strCurrentTimeZone = ((Get-WmiObject @paramGetWmiObject).StandardName) + $TZ = [TimeZoneInfo]::FindSystemTimeZoneById($strCurrentTimeZone) + $LocalTime = [TimeZoneInfo]::ConvertTimeFromUtc($UTCTime, $TZ) + } + + end + { + # Dump it + return $LocalTime + } + } + + # Create a Dummy Object + $Results = @() +} + +process +{ + if ($pscmdlet.ShouldProcess('FrontendPool', 'Get A List of Computers that are members')) + { + try + { + # Cleanup + $FrontendPoolComputers = $null + + # Get all member servers of the Lync pool + $paramGetCsPool = @{ + Identity = $FrontendPool + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $FrontendPoolComputers = ((Get-CsPool @paramGetCsPool).Computers) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about the error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff for troubleshooting + $info | Out-String | Write-Verbose + + # Thow the error and go... + Write-Error -Message "$info.Exception" -ErrorAction Stop + + # This is a point the code should never reach (You told PowerShell to Ignore the ErrorAction above!) + break + + # OK, now we have reached a point the we would never, never ever, see + exit 1 + } + + if (-not $FrontendPoolComputers) + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about the error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff for troubleshooting + $info | Out-String | Write-Verbose + + # Thow the error and go... + Write-Error -Message 'No members of the Lync Pool found...' -ErrorAction Stop + + # This is a point the code should never reach (You told PowerShell to Ignore the ErrorAction above!) + break + + # OK, now we have reached a point the we would never, never ever, see + exit 1 + } + } + + if ($pscmdlet.ShouldProcess('FrontendPool', 'Get A List of Computers that are members')) + { + #Loop Through Front-End Pool + foreach ($Computer in $FrontendPoolComputers) + { + try + { + # Create the Object with a SQL command + $paramInvokeSQLCmd = @{ + ServerInstance = "$Computer\rtclocal" + Database = 'rtcdyn' + Query = "SELECT ActiveConference.ConfId AS 'Conference ID', ActiveConference.Locked, Participant.UserAtHost AS 'Participant', Participant.JoinTime AS 'Join Time', Participant.EnterpriseId, ActiveConference.IsLargeMeeting AS 'Large Meeting' FROM ActiveConference INNER JOIN Participant ON ActiveConference.ConfId = Participant.ConfId;" + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $Result = (Invoke-SQLCmd @paramInvokeSQLCmd) + $Result | Add-Member -NotePropertyName 'Frontend' -NotePropertyValue $Computer + $Result.'Join Time' = Convert-UTCtoLocal -UTCTime $Result.'Join Time' + + # Append + $Results += $Result + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about the error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff for troubleshooting + $info | Out-String | Write-Verbose + + # A simple warning is OK here + Write-Warning -Message "$info.Exception" -WarningAction Continue -ErrorAction Continue + } + } + } +} + +end +{ + if ($Results) + { + # Dump it + $Results + } + else + { + # Thow the error and go... + Write-Error -Message 'No Results found!' -ErrorAction Stop + + # This is a point the code should never reach (You told PowerShell to Ignore the ErrorAction above!) + break + + # OK, now we have reached a point the we would never, never ever, see + exit 1 + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Skype_for_Business/Invoke-FindS4BUsersToDisable.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/Invoke-FindS4BUsersToDisable.ps1 new file mode 100644 index 0000000..1dcfca9 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/Invoke-FindS4BUsersToDisable.ps1 @@ -0,0 +1,119 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Find AD disabled Skype for Business Users + + .DESCRIPTION + Find accounts that are disabled in the Active Directory but are still Skype for Business enabled + + .PARAMETER disable + Should all users that are disbled in the Active Directory also be disabled in Skype for Business + + .EXAMPLE + PS C:\> Invoke-FindS4BUsersToDisable + + # Find AD disabled Skype for Business Users + + .EXAMPLE + PS C:\> Invoke-FindS4BUsersToDisable -disable + + # Find and disable AD disabled Skype for Business Users + + .NOTES + Be carfull with the -disable switch + It might disable monitoring users and/or Skype enabled resource accounts +#> +param +( + [Parameter(Position = 1)] + [Alias('d')] + [switch] + $disable +) + +begin +{ + # Define the defaults + $SC = 'SilentlyContinue' + + # Cleanup + $S4BUsersToDisable = $null +} + +process +{ + # Splat + $paramGetCsAdUser = @{ + ResultSize = 'Unlimited' + ErrorAction = $SC + WarningAction = $SC + } + $S4BUsersToDisable = (Get-CsAdUser @paramGetCsAdUser | Where-Object -FilterScript { + $_.UserAccountControl -match 'AccountDisabled' -and $_.Enabled -eq $true + } | Select-Object -Property Name, Enabled, SipAddress) +} + +end +{ + if ($disable) + { + # Disable all user found + foreach ($S4BUserToDisable in $S4BUsersToDisable) + { + Write-Verbose -Message ('We try to disable {0} now' -f $S4BUserToDisable.SipAddress) + try + { + # Splat + $paramDisableCsUser = @{ + ErrorAction = 'Stop' + WarningAction = $SC + } + $null = ($S4BUserToDisable.SipAddress | Disable-CsUser @paramDisableCsUser) + + Write-Verbose -Message ('The user {0} is now disabled' -f $S4BUserToDisable.SipAddress) + } + catch + { + Write-Warning -Message ('We where unable to disable {0}' -f $S4BUserToDisable.SipAddress) + } + } + } + else + { + # Dump all Users + $S4BUsersToDisable + } + + # Cleanup + $S4BUsersToDisable = $null +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Skype_for_Business/LICENSE b/Powershell/PowerShell-collection/Skype_for_Business/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/Client_GPO.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Client_GPO.ps1 new file mode 100644 index 0000000..9cad7a7 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Client_GPO.ps1 @@ -0,0 +1,824 @@ +<# + .SYNOPSIS + Create the S4B Client QoS Group Policy + + .DESCRIPTION + Create the Skype for Busines related Quality of Services Client Group Policy + + .EXAMPLE + PS C:\> .\Client_GPO.ps1 + + .EXAMPLE + PS C:\> .\Client_GPO.ps1 -verbose + + .NOTES + Check that the ports and port ranges fit your requirements! + + The ports and ranges we use here should fit the Skype for Business Online setup +#> +[CmdletBinding()] +param () + +#Requires -RunAsAdministrator + +BEGIN +{ + #region Variables + + # Ports to use for Application Sharing + [string]$AppSharePorts = '50040:50059' + + # QoS marking for Application Sharing + [string]$AppShareMark = '24' + + # Ports to use for Video + [string]$VideoPorts = '50020:50039' + + # QoS marking for Video + [string]$VideoMark = '34' + + # Ports to use for Audio + [string]$AudioPorts = '50000:50019' + + # QoS marking for Audio + [string]$AudioMark = '46' + + # Ports to use for File Transfer + [string]$FileTransferPorts = '5350:5369' + + # QoS marking for File Transfer + [string]$FileTransferMark = '14' + + # Legacy Media Ports (OCS 2007 R2 Media) + [string]$LegacyMediaPorts = '5370:5389' + + # Lync SIP Ports + [string]$LyncSipPorts = '5390:5409' + + #endregion Variables + + #region Executables + + # Executables + [string]$MediaEngineService = 'MediaEngineService.exe' + [string]$mstsc = 'mstsc.exe' + [string]$LyncStore = 'lyncmx.exe' + [string]$Lync = 'lync.exe' + [string]$Communicator = 'communicator.exe' + [string]$AttendantConsole = 'AttendantConsole.exe' + + #endregion Executables + + #region GroupPolicyInfo + + # GPO (Policy) Name + [string]$PolicyName = 'S4B QoS - Client' + + # GPO (Policy) Comment + [string]$PolicyComment = 'DSCP markings for Lync/Skype for Business client traffic. This GPO should be applied to all Organizational Units (OUs) containing client machines that will use Lync/Skype for Business.' + + #endregion GroupPolicyInfo + + #region Defaults + + # Define some Defaults + [string]$SC = 'SilentlyContinue' + [string]$STP = 'Stop' + [string]$MinusOne = '-1' + [string]$OneZero = '1.0' + [string]$One = '1' + [string]$WC = '*' + [string]$ThrotRate = 'Throttle Rate' + [string]$DscpVal = 'DSCP Value' + [string]$RemIPLen = 'Remote IP Prefix Length' + [string]$RemIP = 'Remote IP' + [string]$RemPort = 'Remote Port' + [string]$LocIPLen = 'Local IP Prefix Length' + [string]$LocIP = 'Local IP' + [string]$LocPort = 'Local Port' + [string]$Protocol = 'Protocol' + [string]$AppName = 'Application Name' + [string]$Version = 'Version' + [string]$STRG = 'String' + [string]$UserSettingsDisabled = 'UserSettingsDisabled' + [string]$ServicesTcpipQoSName = 'HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\QoS' + [string]$ServicesTcpipQoSValue = 'Do not use NLA' + [string]$Action = 'Update' + [string]$Context = 'Computer' + + #endregion Defaults + + #region ModuleHandler + + try + { + # List of Modules + $Modules = 'ActiveDirectory', 'GroupPolicy' + + # Loop over the Module List + foreach ($Module in $Modules) + { + # Import the Module + Write-Verbose -Message ('Importing {0}' -f $Module) + + $null = (Import-Module -Name $Module -ErrorAction $STP -WarningAction $SC) + + Write-Verbose -Message ('Imported {0}' -f $Module) + } + } + catch + { + # Whoops + Write-Error -Message ('Unable to import the {0} Module, please check your Setup!' -f $Module) -ErrorAction $STP + + # We are done here... + break + } + + #endregion ModuleHandler +} + +PROCESS +{ + #region CreateGroupPolicy + + try + { + Write-Verbose -Message ('Try to create {0}' -f $PolicyName) + + #Cleanup + $paramNewGPO = $null + + # Splat reusable parameters + $paramNewGPO = @{ + Name = $PolicyName + Comment = $PolicyComment + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + } + + $null = (New-GPO @paramNewGPO) + + Write-Verbose -Message ('Created {0}' -f $PolicyName) + } + catch + { + Write-Verbose -Message ('The Policy {0} exists' -f $PolicyName) + } + + #endregion CreateGroupPolicy + + #region ModifyGroupPolicy + + try + { + Write-Verbose -Message ('Try to modify {0}' -f $PolicyName) + + $null = ((Get-GPO -Name $PolicyName).GpoStatus = $UserSettingsDisabled) + + Write-Verbose -Message ('Modified {0}' -f $PolicyName) + } + catch + { + Write-Error -Message ('Unable to modify {0}' -f $PolicyName) -ErrorAction $STP + + # We are done here... + break + } + + #endregion ModifyGroupPolicy + + #region ServicesTcpipQoSName + + try + { + Write-Verbose -Message ('Try to Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + + # Cleanup + $paramSetGPPrefRegistryValue = $null + + # Splat reusable parameters + $paramSetGPPrefRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Context = $Context + Key = $ServicesTcpipQoSName + ValueName = $ServicesTcpipQoSValue + Value = $One + Type = $STRG + Action = $Action + } + + $null = (Set-GPPrefRegistryValue @paramSetGPPrefRegistryValue) + + Write-Verbose -Message ('Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + } + + #endregion ServicesTcpipQoSName + + #region communicator_exe + + try + { + Write-Verbose -Message ('Try to set OCS 2007 R2 Media - communicator.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\OCS 2007 R2 Media - communicator.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Communicator, $WC, $LegacyMediaPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set OCS 2007 R2 Media - communicator.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set OCS 2007 R2 Media - communicator.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2010 Audio QoS - communicator.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2010 Audio QoS - communicator.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Communicator, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2010 Audio QoS - communicator.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2010 Audio QoS - communicator.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2010 Video QoS - communicator.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2010 Video QoS - communicator.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Communicator, $WC, $VideoPorts, $WC, $WC, $WC, $WC, $WC, $VideoMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2010 Video QoS - communicator.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2010 Video QoS - communicator.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2010 Application Sharing QoS - communicator.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2010 Application Sharing QoS - communicator.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Communicator, $WC, $AppSharePorts, $WC, $WC, $WC, $WC, $WC, $AppShareMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2010 Application Sharing QoS - communicator.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to Set Lync 2010 Application Sharing QoS - communicator.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2010 File Transfer QoS - communicator.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2010 File Transfer QoS - communicator.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Communicator, $WC, $FileTransferPorts, $WC, $WC, $WC, $WC, $WC, $FileTransferMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2010 File Transfer QoS - communicator.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2010 File Transfer QoS - communicator.exe in {0}' -f $PolicyName) + } + + #endregion communicator_exe + + #region attendantconsole_exe + + try + { + Write-Verbose -Message ('Try to set Lync 2010 Attendant Audio QoS - attendantconsole.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2010 Attendant Audio QoS - attendantconsole.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $AttendantConsole, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2010 Attendant Audio QoS - attendantconsole.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2010 Attendant Audio QoS - attendantconsole.exe in {0}' -f $PolicyName) + } + + #endregion attendantconsole_exe + + #region lync_exe + + try + { + Write-Verbose -Message ('Try to set Lync 2013 Audio QoS - lync.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2013 Audio QoS - lync.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Lync, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2013 Audio QoS - lync.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2013 Audio QoS - lync.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2013 Video QoS - lync.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2013 Video QoS - lync.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Lync, $WC, $VideoPorts, $WC, $WC, $WC, $WC, $WC, $VideoMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2013 Video QoS - lync.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2013 Video QoS - lync.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2013 Application Sharing QoS - lync.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2013 Application Sharing QoS - lync.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Lync, $WC, $AppSharePorts, $WC, $WC, $WC, $WC, $WC, $AppShareMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2013 Application Sharing QoS - lync.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2013 Application Sharing QoS - lync.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2013 File Transfer QoS - lync.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2013 File Transfer QoS - lync.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Lync, $WC, $FileTransferPorts, $WC, $WC, $WC, $WC, $WC, $FileTransferMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2013 File Transfer QoS - lync.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2013 File Transfer QoS - lync.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync 2013 SIP - lync.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync 2013 SIP - lync.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $Lync, $WC, $LyncSipPorts, $WC, $WC, $WC, $WC, $WC, $AppShareMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync 2013 SIP - lync.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync 2013 SIP - lync.exe in {0}' -f $PolicyName) + } + + #endregion lync_exe + + #region lyncmx_exe + + try + { + Write-Verbose -Message ('Try to set Lync Windows Store App Audio QoS - lyncmx.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync Windows Store App Audio QoS - lyncmx.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $LyncStore, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync Windows Store App Audio QoS - lyncmx.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync Windows Store App Audio QoS - lyncmx.exe in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Lync Windows Store App Video QoS - lyncmx.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Lync Windows Store App Video QoS - lyncmx.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $LyncStore, $WC, $VideoPorts, $WC, $WC, $WC, $WC, $WC, $VideoMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Lync Windows Store App Video QoS - lyncmx.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Lync Windows Store App Video QoS - lyncmx.exe in {0}' -f $PolicyName) + } + + #endregion lyncmx_exe + + #region VdiSetup + + try + { + Write-Verbose -Message ('Try to set VDI Audio QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\VDI Audio QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $mstsc, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set VDI Audio QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set VDI Audio QoS in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set VDI Video QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\VDI Video QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $mstsc, $WC, $VideoPorts, $WC, $WC, $WC, $WC, $WC, $VideoMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set VDI Video QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set VDI Video QoS in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set VDI Application Sharing QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\VDI Application Sharing QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $mstsc, $WC, $AppSharePorts, $WC, $WC, $WC, $WC, $WC, $AppShareMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set VDI Application Sharing QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set VDI Application Sharing QoS in {0}' -f $PolicyName) + } + + #endregion VdiSetup + + #region VdiHdxSetup + + try + { + Write-Verbose -Message ('Try to set VDI Audio QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\VDI Audio QoS (Citrix HDX RealTime Optimization Pack 2.0)' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $MediaEngineService, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set VDI Audio QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set VDI Audio QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set VDI Video QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\VDI Video QoS (Citrix HDX RealTime Optimization Pack 2.0)' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $MediaEngineService, $WC, $VideoPorts, $WC, $WC, $WC, $WC, $WC, $VideoMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set VDI Video QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set VDI Video QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set VDI Application Sharing QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\VDI Application Sharing QoS (Citrix HDX RealTime Optimization Pack 2.0)' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $MediaEngineService, $WC, $AppSharePorts, $WC, $WC, $WC, $WC, $WC, $AppShareMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set VDI Application Sharing QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set VDI Application Sharing QoS (Citrix HDX RealTime Optimization Pack 2.0) in {0}' -f $PolicyName) + } + + #endregion VdiHdxSetup +} + +END +{ + Write-Output -InputObject ('Done with the creation of {0}' -f $PolicyName) +} + +#region License + +<# + Copyright (c) 2017, Joerg Hochwald. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + By using the Software, you agree to the License, Terms and Conditions above! +#> + +<# + This is a third-party Software! + + The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + The Software is not supported by Microsoft Corp (MSFT)! +#> + +#endregion License diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/Edge_REG.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Edge_REG.ps1 new file mode 100644 index 0000000..e78fd4c --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Edge_REG.ps1 @@ -0,0 +1,1502 @@ +<# + .SYNOPSIS + Setup the S4B Edge server for QoS + + .DESCRIPTION + Setup the Skype for Business 2015 Edge Server for Quality of Services + Edge Servers are not domain joined, we have to modify the registry instead of using a Group Policy + + .EXAMPLE + PS C:\> .\Edge_REG.ps1 + + .EXAMPLE + PS C:\> .\Edge_REG.ps1 -verbose + + .NOTES + Check that the ports and port ranges fit your requirements! + + The ports and ranges we use here should fit the Skype for Business Online setup +#> +[CmdletBinding()] +param () + +#Requires -RunAsAdministrator + +BEGIN +{ + #region Variables + + # Ports to use for Application Sharing + [string]$AppSharePorts = '50040:50059' + + # QoS marking for Application Sharing + [string]$AppShareMark = '24' + + # Ports to use for Video + [string]$VideoPorts = '50020:50039' + + # QoS marking for Video + [string]$VideoMark = '34' + + # Ports to use for Audio + [string]$AudioPorts = '50000:50019' + + # QoS marking for Audio + [string]$AudioMark = '46' + + #endregion Variables + + #region Defaults + + # Define some Defaults + [string]$SC = 'SilentlyContinue' + [string]$STP = 'Stop' + [string]$DscpVal = 'DSCP Value' + [string]$MinusOne = '-1' + [string]$One = '1' + [string]$OneZero = '1.0' + [string]$WC = '*' + [string]$ThrotRate = 'Throttle Rate' + [string]$RemIPLen = 'Remote IP Prefix Length' + [string]$RemIP = 'Remote IP' + [string]$RemPort = 'Remote Port' + [string]$LocIPLen = 'Local IP Prefix Length' + [string]$LocIP = 'Local IP' + [string]$LocPort = 'Local Port' + [string]$Protocol = 'Protocol' + [string]$Version = 'Version' + [string]$STRG = 'String' + [string]$ServerAppSharePath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\QoS\S4B QoS - Edge - App Sharing' + [string]$ServerVideoPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\QoS\S4B QoS - Edge - Server Video' + [string]$ServerAudioPath = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\QoS\S4B QoS - Edge - Server Audio' + [string]$TcpQosPath = 'HKLM:\SYSTEM\CurrentControlSet\Services\Tcpip\QoS' + [string]$ServicesTcpipQoSValue = 'Do not use NLA' + [string]$IPv4Connectivity = 'LocalNetwork' + [string]$AddressFamily = 'IPv4' + + #endregion Defaults +} + +PROCESS +{ + #region TcpQosPath + + try + { + Write-Verbose -Message ('Create {0}' -f $TcpQosPath) + + # Splat reusable parameters + $paramNewItem = @{ + Path = $TcpQosPath + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-Item @paramNewItem) + + Write-Verbose -Message ('Created {0}' -f $TcpQosPath) + } + catch + { + Write-Verbose -Message ('Unable to create {0}' -f $TcpQosPath) + } + + try + { + Write-Verbose -Message ('Try to create {0} in {1} with value {2}' -f $ServicesTcpipQoSValue, $TcpQosPath, $One) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $TcpQosPath + Name = $ServicesTcpipQoSValue + Value = $One + PropertyType = $STRG + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} in {1} with value {2}' -f $ServicesTcpipQoSValue, $TcpQosPath, $One) + } + catch + { + # Try to modify it instead + try + { + Write-Verbose -Message ('Try to modify {0} in {1} with value {2}' -f $ServicesTcpipQoSValue, $TcpQosPath, $One) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} in {1} with value {2}' -f $ServicesTcpipQoSValue, $TcpQosPath, $One) + } + catch + { + # Whoooops + Write-Warning -Message ('Unable to set {0} in {1} to {2}' -f $ServicesTcpipQoSValue, $TcpQosPath, $One) + } + } + + #endregion TcpQosPath + + #region GetIpInfo + + <# + Check if this matches your Edge configuration!!! + #> + try + { + # Cleanup + $paramGetNetConnectionProfile = $null + + # Splat reusable parameters + $paramGetNetConnectionProfile = @{ + ErrorAction = $STP + WarningAction = $SC + } + + # Get the first Interface (See internal above) + [int] $Adapter = (Get-NetConnectionProfile @paramGetNetConnectionProfile | Where-Object -FilterScript { + $_.IPv4Connectivity -eq $IPv4Connectivity + }).InterfaceIndex | Select-Object -First $One + + # Cleanup + $IP = $null + $paramGetNetIPAddress = $null + + + # Splat reusable parameters + $paramGetNetIPAddress = @{ + InterfaceIndex = $Adapter + AddressFamily = $AddressFamily + ErrorAction = $STP + WarningAction = $SC + } + + # The IP of the Interface + [string]$IP = (Get-NetIPAddress @paramGetNetIPAddress ).ipaddress + + # check if IP exists + if (-not $IP) + { + # Nothing fancy, we just need a stop here + throw + } + + #endregion GetIpInfo + + #region ServerAudioPath + + try + { + Write-Verbose -Message ('Try to create {0}' -f $ServerAudioPath) + + # Cleanup + $paramNewItem = $null + + # Splat reusable parameters + $paramNewItem = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $SC + } + $null = (New-Item @paramNewItem) + + Write-Verbose -Message ('Created {0}' -f $ServerAudioPath) + } + catch + { + Write-Verbose -Message ('Unable to create {0}' -f $ServerAudioPath) + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $Protocol + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to set {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $DscpVal, $AudioMark, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $DscpVal + Value = $AudioMark + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $DscpVal, $AudioMark, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to Modify {0} with value {1} as {2} in {3}' -f $DscpVal, $AudioMark, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $DscpVal, $AudioMark, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $DscpVal, $AudioMark, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocIP + Value = $IP + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocIPLen + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Create {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocPort, $AudioPorts, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocPort + Value = $AudioPorts + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $LocPort, $AudioPorts, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocPort, $AudioPorts, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocPort, $AudioPorts, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocPort, $AudioPorts, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemIP + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemIPLen + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemPort + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $ThrotRate + Value = $MinusOne + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAudioPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAudioPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAudioPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $Version + Value = $OneZero + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAudioPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAudioPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAudioPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAudioPath) + } + } + + #endregion ServerAudioPath + + #region ServerVideoPath + + try + { + Write-Verbose -Message ('Try to create {0}' -f $ServerVideoPath) + + # Cleanup + $paramNewItem = $null + + # Splat reusable parameters + $paramNewItem = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-Item @paramNewItem) + + Write-Verbose -Message ('Created {0}' -f $ServerVideoPath) + } + catch + { + Write-Verbose -Message ('Unable to create {0}' -f $ServerVideoPath) + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $Protocol + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $DscpVal, $VideoMark, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $DscpVal + Value = $VideoMark + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $DscpVal, $VideoMark, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $DscpVal, $VideoMark, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $DscpVal, $VideoMark, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $DscpVal, $VideoMark, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocIP + Value = $IP + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocIPLen + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocPort, $VideoPorts, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocPort + Value = $VideoPorts + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('created {0} with value {1} as {2} in {3}' -f $LocPort, $VideoPorts, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocPort, $VideoPorts, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocPort, $VideoPorts, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocPort, $VideoPorts, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemIP + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemIPLen + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemPort + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $ThrotRate + Value = $MinusOne + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerVideoPath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerVideoPath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerVideoPath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $Version + Value = $OneZero + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerVideoPath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerVideoPath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerVideoPath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerVideoPath) + } + } + + #endregion ServerVideoPath + + #region ServerAppSharePath + + try + { + Write-Verbose -Message ('Try to create {0}' -f $ServerAppSharePath) + + # Cleanup + $paramNewItem = $null + + # Splat reusable parameters + $paramNewItem = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-Item @paramNewItem) + + Write-Verbose -Message ('Created {0}' -f $ServerAppSharePath) + } + catch + { + Write-Verbose -Message ('Unable to create {0}' -f $ServerAppSharePath) + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $Protocol + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to Modify {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $Protocol, $WC, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $DscpVal, $AppShareMark, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $DscpVal + Value = $AppShareMark + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $DscpVal, $AppShareMark, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to Modify {0} with value {1} as {2} in {2}' -f $DscpVal, $AppShareMark, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $DscpVal, $AppShareMark, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $DscpVal, $AppShareMark, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocIP + Value = $IP + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocIP, $IP, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocIPLen + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocIPLen, $WC, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $LocPort, $AppSharePorts, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $LocPort + Value = $AppSharePorts + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $LocPort, $AppSharePorts, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $LocPort, $AppSharePorts, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $LocPort, $AppSharePorts, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $LocPort, $AppSharePorts, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemIP + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to moddify {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemIP, $WC, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemIPLen + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemIPLen, $WC, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $RemPort + Value = $WC + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $RemPort, $WC, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $ThrotRate + Value = $MinusOne + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $ThrotRate, $MinusOne, $STRG, $ServerAppSharePath) + } + } + + try + { + Write-Verbose -Message ('Try to create {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAppSharePath) + + # Cleanup + $paramNewItemProperty = $null + + # Splat reusable parameters + $paramNewItemProperty = @{ + Path = $ServerAppSharePath + Force = $true + Confirm = $false + PropertyType = $STRG + Name = $Version + Value = $OneZero + ErrorAction = $STP + WarningAction = $SC + } + + $null = (New-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Created {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAppSharePath) + } + catch + { + try + { + Write-Verbose -Message ('Try to modify {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAppSharePath) + + $null = (Set-ItemProperty @paramNewItemProperty) + + Write-Verbose -Message ('Modified {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAppSharePath) + } + catch + { + Write-Warning -Message ('Unable to create {0} with value {1} as {2} in {3}' -f $Version, $OneZero, $STRG, $ServerAppSharePath) + } + } + + #endregion ServerAppSharePath + } + catch + { + Write-Error -Message 'Unable to find the IP Address of the Edge Node.' -ErrorAction $STP + + # Make sure we are done + break + } +} + +END +{ + Write-Output -InputObject 'Done with the Skype for Business Edge Server QoS setup, Please Reboot this node.' +} + +#region License + +<# + Copyright (c) 2017, Joerg Hochwald. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + By using the Software, you agree to the License, Terms and Conditions above! +#> + +<# + This is a third-party Software! + + The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + The Software is not supported by Microsoft Corp (MSFT)! +#> + +#endregion License diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/ExchangeUM_GPO.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/QoS/ExchangeUM_GPO.ps1 new file mode 100644 index 0000000..1fd220c --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/ExchangeUM_GPO.ps1 @@ -0,0 +1,357 @@ +<# + .SYNOPSIS + Create the S4B Related Exchange UM QoS Group Policy + + .DESCRIPTION + Create the Skype for Busines related Exchange Unified Messaging Quality of Services Group Policy + + .EXAMPLE + PS C:\> .\ExchangeUM_GPO.ps1 + + .EXAMPLE + PS C:\> .\ExchangeUM_GPO.ps1 -verbose + + .NOTES + Check that the ports and port ranges fit your requirements! + + The ports and ranges we use here should fit the Skype for Business Online setup +#> +[CmdletBinding()] +param () + +#Requires -RunAsAdministrator + +BEGIN +{ + #region Variables + + # QoS marking for Audio + $SC = 'SilentlyContinue' + $STP = 'Stop' + [string]$AudioMark = '46' + + #endregion Variables + + #region GroupPolicyInfo + + # GPO (Policy) Name + [string]$PolicyName = 'S4B QoS - Exchange UM' + + # GPO (Policy) Comment + [string]$PolicyComment = 'DSCP markings for Exchange UM traffic. This GPO should be applied to all Organizational Units (OUs) containing Exchange UM servers.' + + #endregion GroupPolicyInfo + + #region Defaults + + # Define some Defaults + [string]$MinusOne = '-1' + [string]$OneZero = '1.0' + [string]$One = '1' + [string]$WC = '*' + [string]$ThrotRate = 'Throttle Rate' + [string]$DscpVal = 'DSCP Value' + [string]$RemIPLen = 'Remote IP Prefix Length' + [string]$RemIP = 'Remote IP' + [string]$RemPort = 'Remote Port' + [string]$LocIPLen = 'Local IP Prefix Length' + [string]$LocIP = 'Local IP' + [string]$LocPort = 'Local Port' + [string]$Protocol = 'Protocol' + [string]$AppName = 'Application Name' + [string]$Version = 'Version' + [string]$STRG = 'String' + [string]$UserSettingsDisabled = 'UserSettingsDisabled' + [string]$ServicesTcpipQoSName = 'HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\QoS' + [string]$ServicesTcpipQoSValue = 'Do not use NLA' + [string]$Action = 'Update' + [string]$Context = 'Computer' + + #endregion Defaults + + #region ModuleHandler + + try + { + # List of Modules + $Modules = 'ActiveDirectory', 'GroupPolicy' + + # Loop over the Module List + foreach ($Module in $Modules) + { + # Import the Module + Write-Verbose -Message ('Importing {0}' -f $Module) + + $null = (Import-Module -Name $Module -ErrorAction $STP -WarningAction $SC) + + Write-Verbose -Message ('Imported {0}' -f $Module) + } + } + catch + { + # Whoops + Write-Error -Message ('Unable to import the {0} Module, please check your Setup!' -f $Module) -ErrorAction $STP + + # We are done here... + break + } + + #endregion ModuleHandler +} + +PROCESS +{ + #region CreateGroupPolicy + + try + { + Write-Verbose -Message ('Try to create {0}' -f $PolicyName) + + #Cleanup + $paramNewGPO = $null + + # Splat reusable parameters + $paramNewGPO = @{ + Name = $PolicyName + Comment = $PolicyComment + ErrorAction = Stop + WarningAction = SilentlyContinue + Confirm = $false + } + + $null = (New-GPO @paramNewGPO) + + Write-Verbose -Message ('Created {0}' -f $PolicyName) + } + catch + { + Write-Verbose -Message ('The Policy {0} exists' -f $PolicyName) + } + + #endregion CreateGroupPolicy + + #region ModifyGroupPolicy + + try + { + Write-Verbose -Message ('Try to modify {0}' -f $PolicyName) + + $null = ((Get-GPO -Name $PolicyName).GpoStatus = $UserSettingsDisabled) + + Write-Verbose -Message ('Modified {0}' -f $PolicyName) + } + catch + { + Write-Error -Message ('Unable to modify {0}' -f $PolicyName) -ErrorAction $STP + + # We are done here... + break + } + + #endregion ModifyGroupPolicy + + #region ServicesTcpipQoSName + + try + { + Write-Verbose -Message ('Try to Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + + # Cleanup + $paramSetGPPrefRegistryValue = $null + + # Splat reusable parameters + $paramSetGPPrefRegistryValue = @{ + Name = $PolicyName + ErrorAction = Stop + WarningAction = SilentlyContinue + Context = $Context + Key = $ServicesTcpipQoSName + ValueName = $ServicesTcpipQoSValue + Value = $One + Type = $STRG + Action = $Action + } + + $null = (Set-GPPrefRegistryValue @paramSetGPPrefRegistryValue) + + Write-Verbose -Message ('Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + } + + #endregion ServicesTcpipQoSName + + #region EdgeToExchangeAudio + + try + { + Write-Verbose -Message ('Try to set Edge to Exchange UM Audio QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Edge to Exchange UM Audio QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $WC, $WC, '1024:65535', $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Edge to Exchange UM Audio QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Edge to Exchange UM Audio QoS in {0}' -f $PolicyName) + } + + #endregion EdgeToExchangeAudio + + #region umservices_exe + + try + { + Write-Verbose -Message ('Try to set Exchange UM Audio to Edge QoS - umservices.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Exchange UM Audio to Edge QoS - umservices.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, 'umservices.exe', $WC, '', $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Exchange UM Audio to Edge QoS - umservices.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Exchange UM Audio to Edge QoS - umservices.exe in {0}' -f $PolicyName) + } + + #endregion umservices_exe + + #region Microsoft_Exchange_UM_CallRouter_exe + + try + { + Write-Verbose -Message ('Try to set Exchange UM Audio to Edge QoS - Microsoft.Exchange.UM.CallRouter.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Exchange UM Audio to Edge QoS - Microsoft.Exchange.UM.CallRouter.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, 'Microsoft.Exchange.UM.CallRouter.exe', $WC, '', $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Exchange UM Audio to Edge QoS - Microsoft.Exchange.UM.CallRouter.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Exchange UM Audio to Edge QoS - Microsoft.Exchange.UM.CallRouter.exe in {0}' -f $PolicyName) + } + + #endregion Microsoft_Exchange_UM_CallRouter_exe + + #region umworkerprocess_exe + + try + { + Write-Verbose -Message ('Try to set Exchange UM Audio to Edge QoS - umworkerprocess.exe in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Exchange UM Audio to Edge QoS - umworkerprocess.exe' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, 'umworkerprocess.exe', $WC, '', $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Exchange UM Audio to Edge QoS - umworkerprocess.exe in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Exchange UM Audio to Edge QoS - umworkerprocess.exe in {0}' -f $PolicyName) + } + + #endregion umworkerprocess_exe +} + +END +{ + Write-Output -InputObject ('Done with the creation of {0}' -f $PolicyName) +} + +#region License + +<# + Copyright (c) 2017, Joerg Hochwald. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + By using the Software, you agree to the License, Terms and Conditions above! +#> + +<# + This is a third-party Software! + + The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + The Software is not supported by Microsoft Corp (MSFT)! +#> + +#endregion License diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/LICENSE b/Powershell/PowerShell-collection/Skype_for_Business/QoS/LICENSE new file mode 100644 index 0000000..c6e8f8c --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2019, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/Server_GPO.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Server_GPO.ps1 new file mode 100644 index 0000000..912982d --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Server_GPO.ps1 @@ -0,0 +1,500 @@ +<# + .SYNOPSIS + Create the S4B Server QoS Group Policy + + .DESCRIPTION + Create the Skype for Busines related Quality of Services Server Group Policy + + .EXAMPLE + PS C:\> .\Server_GPO.ps1 + + .EXAMPLE + PS C:\> .\Server_GPO.ps1 -verbose + + .NOTES + Check that the ports and port ranges fit your requirements! + + The ports and ranges we use here should fit the Skype for Business Online setup +#> +[CmdletBinding()] +param () + +#Requires -RunAsAdministrator + +BEGIN +{ + #region Variables + + # Ports to use for Application Sharing + [string]$AppSharePorts = '50040:50059' + + # QoS marking for Application Sharing + [string]$AppShareMark = '24' + + # Ports to use for Video + [string]$VideoPorts = '50020:50039' + + # QoS marking for Video + [string]$VideoMark = '34' + + # Ports to use for Audio + [string]$AudioPorts = '50000:50019' + + # QoS marking for Audio + [string]$AudioMark = '46' + + #endregion Variables + + #region GroupPolicyInfo + + # GPO (Policy) Name + [string]$PolicyName = 'S4B QoS - Server' + + # GPO (Policy) Comment + [string]$PolicyComment = 'DSCP markings for Lync/Skype for Business front end server traffic. This GPO should be applied to all Organizational Units (OUs) containing Lync/Skype for Business front-end servers.' + + #endregion GroupPolicyInfo + + #region Executables + + # Executables + [string]$OcsAppServerHost = 'OcsAppServerHost.exe' + [string]$avmcusvc = 'avmcusvc.exe' + [string]$asmcusvc = 'asmcusvc.exe' + + #endregion Executables + + #region Defaults + + # Define some Defaults + [string]$SC = 'SilentlyContinue' + [string]$STP = 'Stop' + [string]$MinusOne = '-1' + [string]$OneZero = '1.0' + [string]$One = '1' + [string]$WC = '*' + [string]$ThrotRate = 'Throttle Rate' + [string]$DscpVal = 'DSCP Value' + [string]$RemIPLen = 'Remote IP Prefix Length' + [string]$RemIP = 'Remote IP' + [string]$RemPort = 'Remote Port' + [string]$LocIPLen = 'Local IP Prefix Length' + [string]$LocIP = 'Local IP' + [string]$LocPort = 'Local Port' + [string]$Protocol = 'Protocol' + [string]$AppName = 'Application Name' + [string]$Version = 'Version' + [string]$STRG = 'String' + [string]$UserSettingsDisabled = 'UserSettingsDisabled' + [string]$ServicesTcpipQoSName = 'HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\QoS' + [string]$ServicesTcpipQoSValue = 'Do not use NLA' + [string]$Action = 'Update' + [string]$Context = 'Computer' + + #endregion Defaults + + #region ModuleHandler + + try + { + # List of Modules + $Modules = 'ActiveDirectory', 'GroupPolicy' + + # Loop over the Module List + foreach ($Module in $Modules) + { + # Import the Module + Write-Verbose -Message ('Importing {0}' -f $Module) + + $null = (Import-Module -Name $Module -ErrorAction $STP -WarningAction $SC) + + Write-Verbose -Message ('Imported {0}' -f $Module) + } + } + catch + { + # Whoops + Write-Error -Message ('Unable to import the {0} Module, please check your Setup!' -f $Module) -ErrorAction $STP + + # We are done here... + break + } + + #endregion ModuleHandler +} + +PROCESS +{ + #region CreateGroupPolicy + + try + { + Write-Verbose -Message ('Try to create {0}' -f $PolicyName) + + #Cleanup + $paramNewGPO = $null + + # Splat reusable parameters + $paramNewGPO = @{ + Name = $PolicyName + Comment = $PolicyComment + ErrorAction = Stop + WarningAction = SilentlyContinue + Confirm = $false + } + + $null = (New-GPO @paramNewGPO) + + Write-Verbose -Message ('Created {0}' -f $PolicyName) + } + catch + { + Write-Verbose -Message ('The Policy {0} exists' -f $PolicyName) + } + + #endregion CreateGroupPolicy + + #region ModifyGroupPolicy + + try + { + Write-Verbose -Message ('Try to modify {0}' -f $PolicyName) + + $null = ((Get-GPO -Name $PolicyName).GpoStatus = $UserSettingsDisabled) + + Write-Verbose -Message ('Modified {0}' -f $PolicyName) + } + catch + { + Write-Error -Message ('Unable to modify {0}' -f $PolicyName) -ErrorAction $STP + + # We are done here... + break + } + + #endregion ModifyGroupPolicy + + #region ServicesTcpipQoSName + + try + { + Write-Verbose -Message ('Try to Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + + # Cleanup + $paramSetGPPrefRegistryValue = $null + + # Splat reusable parameters + $paramSetGPPrefRegistryValue = @{ + Name = $PolicyName + ErrorAction = Stop + WarningAction = SilentlyContinue + Context = $Context + Key = $ServicesTcpipQoSName + ValueName = $ServicesTcpipQoSValue + Value = $One + Type = $STRG + Action = $Action + } + + $null = (Set-GPPrefRegistryValue @paramSetGPPrefRegistryValue) + + Write-Verbose -Message ('Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to Set {0} to {1} {2} in {3}' -f $ServicesTcpipQoSName, $ServicesTcpipQoSValue, $One, $PolicyName) + } + + #endregion ServicesTcpipQoSName + + #region ServerConferencing + + try + { + Write-Verbose -Message ('Try to set Server Conferencing Audio QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server Conferencing Audio QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $avmcusvc, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server Conferencing Audio QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server Conferencing Audio QoS in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Server Conferencing Video QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server Conferencing Video QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $avmcusvc, $WC, $VideoPorts, $WC, $WC, $WC, $WC, $WC, $VideoMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server Conferencing Video QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server Conferencing Video QoS in {0}' -f $PolicyName) + } + + #endregion ServerConferencing + + #region ServerApplicationSharing + + try + { + Write-Verbose -Message ('Try to set Server Application Sharing QoS in {0}' -f $PolicyName) + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server Application Sharing QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $asmcusvc, $WC, $AppSharePorts, $WC, $WC, $WC, $WC, $WC, $AppShareMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server Application Sharing QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server Application Sharing QoS in {0}' -f $PolicyName) + } + + #endregion ServerApplicationSharing + + #region ServerResponseGroup + + try + { + Write-Verbose -Message ('Try to set Server Response Group QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server Response Group QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $OcsAppServerHost, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server Response Group QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server Response Group QoS in {0}' -f $PolicyName) + } + + #endregion ServerResponseGroup + + #region ServerConferenceAnnouncement + + try + { + Write-Verbose -Message ('Try to set Server Conference Announcement Service QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server Conference Announcement Service QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $OcsAppServerHost, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server Conference Announcement Service QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server Conference Announcement Service QoS in {0}' -f $PolicyName) + } + + #endregion ServerConferenceAnnouncement + + #region ServerCallPark + + try + { + Write-Verbose -Message ('Try to set Server Call Park QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server Call Park QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $OcsAppServerHost, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server Call Park QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server Call Park QoS in {0}' -f $PolicyName) + } + + #endregion ServerCallPark + + #region ServerUCMAApplications + + try + { + Write-Verbose -Message ('Try to set Server UCMA Applications Audio QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server UCMA Applications Audio QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $OcsAppServerHost, $WC, $AudioPorts, $WC, $WC, $WC, $WC, $WC, $AudioMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server UCMA Applications Audio QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server UCMA Applications Audio QoS in {0}' -f $PolicyName) + } + + try + { + Write-Verbose -Message ('Try to set Server UCMA Applications Video QoS in {0}' -f $PolicyName) + + # Cleanup + $paramSetGPRegistryValue = $null + + # Splat reusable parameters + $paramSetGPRegistryValue = @{ + Name = $PolicyName + ErrorAction = $STP + WarningAction = $SC + Confirm = $false + Key = 'HKLM\SOFTWARE\Policies\Microsoft\Windows\QoS\Server UCMA Applications Video QoS' + ValueName = $Version, $AppName, $Protocol, $LocPort, $LocIP, $LocIPLen, $RemPort, $RemIP, $RemIPLen, $DscpVal, $ThrotRate + Type = $STRG + Value = $OneZero, $OcsAppServerHost, $WC, $VideoPorts, $WC, $WC, $WC, $WC, $WC, $VideoMark, $MinusOne + } + + $null = (Set-GPRegistryValue @paramSetGPRegistryValue) + + Write-Verbose -Message ('Set Server UCMA Applications Video QoS in {0}' -f $PolicyName) + } + catch + { + Write-Warning -Message ('Unable to set Server UCMA Applications Video QoS in {0}' -f $PolicyName) + } + + #endregion ServerUCMAApplications +} + +END +{ + Write-Output -InputObject ('Done with the creation of {0}' -f $PolicyName) +} + +#region License + +<# + Copyright (c) 2017, Joerg Hochwald. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + By using the Software, you agree to the License, Terms and Conditions above! +#> + +<# + This is a third-party Software! + + The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + The Software is not supported by Microsoft Corp (MSFT)! +#> + +#endregion License diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/Skype_Server_Config.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Skype_Server_Config.ps1 new file mode 100644 index 0000000..6dd5974 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/Skype_Server_Config.ps1 @@ -0,0 +1,443 @@ +<# + .SYNOPSIS + Setup the S4B server for QoS + + .DESCRIPTION + Setup the Skype for Business 2015 Server for Quality of Services + + .PARAMETER FrontEndPool + Skype for Business Front End Pool + + .PARAMETER EdgePool + Skype for Business Edge Pool + + .EXAMPLE + PS C:\> .\Skype_Server_Config.ps1 + + .EXAMPLE + PS C:\> .\Skype_Server_Config.ps1 -verbose + + .NOTES + Check that the ports and port ranges fit your requirements! + + The ports and ranges we use here should fit the Skype for Business Online setup +#> +[CmdletBinding()] +param +( + [Parameter(ValueFromPipeline, + Position = 1)] + [string] + $FrontEndPool = 's4bfe.fra.hicts.net', + [Parameter(ValueFromPipeline, + Position = 2)] + [string] + $EdgePool = 's4bedge.dmz.hicts.net' +) + +#Requires -RunAsAdministrator + +BEGIN +{ + #region Variables + + # QoS marking for Audio + [string]$AudioMark = '46' + + # Audio Start Port + [string]$AudioPortStart = '50000' + + # Number of Ports to use + [string]$AudioPortCount = '20' + + # Video Start Port + [string]$VideoPortStart = ([int]$AudioPortStart + [int]$AudioPortCount) + # Legacy variante of the above (without calculating) + #[string]$VideoPortStart = '50020' + + # Number of Ports to use + [string]$VideoPortCount = '20' + + # App Sharing Start Port + [string]$AppSharingPortStart = ([int]$VideoPortStart + [int]$VideoPortCount) + # Legacy variante of the above (without calculating) + #[string]$AppSharingPortStart = '50040' + + # Number of Ports to use + [string]$AppSharingPortCount = '20' + + # Start File Transfer Port + [string]$ClientFileTransferPort = '5350' + + # Number of Ports to use + [string]$ClientFileTransferPortRange = '20' + + # Start Legacy Media Port + [string]$ClientMediaPort = '5370' + + # Number of Ports to use (Legacy) + [string]$ClientMediaPortRange = '20' + + # Number of Ports to use (Legacy) + [string]$MediaCommunicationPortCount = '10000' + + <# + + # Legacy variables + + # Skype for Business Front End Pool + [string]$FrontEndPool = 's4bfe.fra.hicts.net' + + # Skype for Business Edge Pool + [string]$EdgePool = 's4bedge.dmz.hicts.net' + #> + + #endregion Variables + + #region Defaults + + # Define some Defaults + [string]$SC = 'SilentlyContinue' + [string]$STP = 'Stop' + [string]$Global = 'global' + [string]$Voice8021p = '0' + + #endregion Defaults + + #region CheckCmd + + # All Skype for Business Server related commands + $AllCommands = 'Set-CsConferencingConfiguration', 'Set-CsUCPhoneConfiguration', 'Set-CsMediaConfiguration', 'Set-CsConferenceServer', 'Set-CsApplicationServer', 'Set-CsMediationServer', 'Set-CsWebServer', 'Set-CsEdgeServer' + + # Loop over the list of commands + foreach ($TheCommand in $AllCommands) + { + try + { + Write-Verbose -Message ('Check for {0}' -f $TheCommand) + + # Cleanup + $paramGetCommand = $null + + # Splat reusable parameters + $paramGetCommand = @{ + Name = $TheCommand + ErrorAction = $STP + WarningAction = $SC + } + $null = (Get-Command @paramGetCommand) + + Write-Verbose -Message ('Found {0}' -f $TheCommand) + } + catch + { + # Whoops + $paramWriteError = @{ + Message = ('Unable to find {0} - Please check your Setup!' -f $TheCommand) + ErrorAction = $STP + } + Write-Error @paramWriteError + + # We are done here... + break + } + } + + #endregion CheckCmd +} + +PROCESS +{ + #region ConferencingConfiguration + + try + { + Write-Verbose -Message 'Change Conferencing Configuration' + + # Cleanup + $paramSetCsConferencingConfiguration = $null + + # Splat reusable parameters + $paramSetCsConferencingConfiguration = @{ + Identity = $Global + ClientAudioPort = $AudioPortStart + ClientAudioPortRange = $AudioPortCount + ClientVideoPort = $VideoPortStart + ClientVideoPortRange = $VideoPortCount + ClientAppSharingPort = $AppSharingPortStart + ClientAppSharingPortRange = $AppSharingPortCount + ClientFileTransferPort = $ClientFileTransferPort + ClientFileTransferPortRange = $ClientFileTransferPortRange + ClientMediaPortRangeEnabled = $true + ClientMediaPort = $ClientMediaPort + ClientMediaPortRange = $ClientMediaPortRange + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsConferencingConfiguration @paramSetCsConferencingConfiguration) + + Write-Verbose -Message 'Changed Conferencing Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set Conferencing Configuration' + } + + #endregion ConferencingConfiguration + + #region ChangeUCPhoneConfiguration + + try + { + Write-Verbose -Message 'Change UC Phone Configuration' + + # Cleanup + $paramSetCsUCPhoneConfiguration = $null + + # Splat reusable parameters + $paramSetCsUCPhoneConfiguration = @{ + Identity = $Global + VoiceDiffServTag = $AudioMark + Voice8021p = $Voice8021p + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsUCPhoneConfiguration @paramSetCsUCPhoneConfiguration) + + Write-Verbose -Message 'Changed UC Phone Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set UC Phone Configuration' + } + + #endregion ChangeUCPhoneConfiguration + + #region ChangeMediaConfiguration + + try + { + Write-Verbose -Message 'Change Media Configuration' + + # Cleanup + $paramSetCsMediaConfiguration = $null + + # Splat reusable parameters + $paramSetCsMediaConfiguration = @{ + Identity = $Global + EnableQoS = $true + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsMediaConfiguration @paramSetCsMediaConfiguration) + + Write-Verbose -Message 'Changed Media Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set Media Configuration' + } + + #endregion ChangeMediaConfiguration + + #region ChangeConferenceServerConfiguration + + try + { + Write-Verbose -Message 'Change Conference Server Configuration' + + # Cleanup + $paramSetCsConferenceServer = $null + + # Splat reusable parameters + $paramSetCsConferenceServer = @{ + Identity = $FrontEndPool + AppSharingPortStart = $AppSharingPortStart + AppSharingPortCount = $AppSharingPortCount + AudioPortStart = $AudioPortStart + AudioPortCount = $AudioPortCount + VideoPortStart = $VideoPortStart + VideoPortCount = $VideoPortCount + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsConferenceServer @paramSetCsConferenceServer) + + Write-Verbose -Message 'Changed Conference Server Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set Conference Server Configuration' + } + + #endregion ChangeConferenceServerConfiguration + + #region ChangeApplicationServerConfiguration + + try + { + Write-Verbose -Message 'Change Application Server Configuration' + + # Cleanup + $paramSetCsApplicationServer = $null + + # Splat reusable parameters + $paramSetCsApplicationServer = @{ + Identity = $FrontEndPool + AppSharingPortStart = $AppSharingPortStart + AppSharingPortCount = $AppSharingPortCount + AudioPortStart = $AudioPortStart + AudioPortCount = $AudioPortCount + VideoPortStart = $VideoPortStart + VideoPortCount = $VideoPortCount + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsApplicationServer @paramSetCsApplicationServer) + + Write-Verbose -Message 'Changed Application Server Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set Application Server Configuration' + } + + #endregion ChangeApplicationServerConfiguration + + #region ChangeMediationServerConfiguration + + try + { + Write-Verbose -Message 'Change Mediation Server Configuration' + + #Cleanup + $paramSetCsMediationServer = $null + + + # Splat reusable parameters + $paramSetCsMediationServer = @{ + Identity = $FrontEndPool + AudioPortStart = $AudioPortStart + AudioPortCount = $AudioPortCount + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsMediationServer @paramSetCsMediationServer) + + Write-Verbose -Message 'Changed Mediation Server Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set Mediation Server Configuration' + } + + #endregion ChangeMediationServerConfiguration + + #region ChangeWebServerConfiguration + + try + { + Write-Verbose -Message 'Change Web Server Configuration' + + #Cleanup + $paramSetCsWebServer = $null + + # Splat reusable parameters + $paramSetCsWebServer = @{ + Identity = $FrontEndPool + AppSharingPortStart = $AppSharingPortStart + AppSharingPortCount = $AppSharingPortCount + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsWebServer @paramSetCsWebServer) + + Write-Verbose -Message 'Changed Web Server Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set Web Server Configuration' + } + + #endregion ChangeWebServerConfiguration + + #region ChangeEdgeServerConfiguration + + try + { + Write-Verbose -Message 'Change Edge Server Configuration' + + # Cleanup + $paramSetCsEdgeServer = $null + + # Splat reusable parameters + $paramSetCsEdgeServer = @{ + Identity = $EdgePool + MediaCommunicationPortStart = $AudioPortStart + MediaCommunicationPortCount = $MediaCommunicationPortCount + ErrorAction = $STP + WarningAction = $SC + } + + $null = (Set-CsEdgeServer @paramSetCsEdgeServer) + + Write-Verbose -Message 'Changed Edge Server Configuration' + } + catch + { + Write-Warning -Message 'Unable to Set Edge Server Configuration' + } + + #endregion ChangeEdgeServerConfiguration +} + +END +{ + Write-Output -InputObject 'Done with the Skype for Business QoS setup.' +} + +#region License + +<# + Copyright (c) 2017, Joerg Hochwald. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + By using the Software, you agree to the License, Terms and Conditions above! +#> + +<# + This is a third-party Software! + + The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + The Software is not supported by Microsoft Corp (MSFT)! +#> + +#endregion License diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/readme.md b/Powershell/PowerShell-collection/Skype_for_Business/QoS/readme.md new file mode 100644 index 0000000..d7338b1 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/readme.md @@ -0,0 +1,8 @@ +# Legacy Notice + +I no longer run Exchange, Skype for Business, or any other Office Server on Premises. +This is my personal [reaction](https://hochwald.net/microsoft-rolls-back-decision-to-take-away-internal-usage-rights-from-partners/) to the changes that Microsoft [announced](https://hochwald.net/microsoft-is-going-to-kill-internal-use-rights-benefit-for-partners/) for the Internal Use Rights (IUR) program. I know that they decided to reverse that changes and in theory, I could still legally use the software. However, I decided to decommission everything licensed under the terms of the Internal Use Rights (IUR) program. +In my opinion, the community always should have some benefits from the Internal Use Rights (IUR) program and/or Action Pack. Now that I decided to drop out, there will be no more such benefits. + +I will _no longer maintain_ the scripts related to the Microsoft Office (on Premises) servers. They will remain here, but unmaintained. Fork the repository and maintain or extend them if you like to. The [License](https://github.com/jhochwald/PowerShell-collection/blob/master/LICENSE) allows that easily. + diff --git a/Powershell/PowerShell-collection/Skype_for_Business/QoS/readme_old.md b/Powershell/PowerShell-collection/Skype_for_Business/QoS/readme_old.md new file mode 100644 index 0000000..6d250f9 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/QoS/readme_old.md @@ -0,0 +1,63 @@ +# Skype for Business QoS Settings +Setup Quality of Services (QoS) on Skype for Business Servers and Clients. + +## You Network +You must configure your network equipment to match the marks that are configured on the client/server part. + +Some people get this QoS wrong: This configuration enables your Clients and Servers to mark the traffic! Not more, not less. Your network equipment must do the dirty work and prioritize and/or reserve bandwidth that match your requirements. + +If you just load the stuff here, nothing will change. Your Skype Clients and servers will mark the packets and that's about it! + +## What it does +It configures the Skype for Business Servers to use a small range of ports for each function (e.g. Voice or Video). This range should match the Skype for Business Online (SfBO) configuration. +All Skype for Business Clients should use these configuration after a restart/re-login. Even non-Windows clients will be using the configuration, because it is configured on the server. + +For Skype for Business Servers and Windows Based Clients, a dedicated Group Policy will be established. You should apply these to all OU's where the Clients and/or Servers are located. +The Client Policy also contains configuration/settings for VDI instances, and even for Citrix HDX setup's. + +There is also the matching Edge configuration, these boxes should never be domain joined. Therefore, we use local registry settings! + +To make the end-to-end setup, there is also a dedicated Group Policy for Exchange Servers. This Policy should be applied at minimum to all Exchange Servers that hosts the Unified Messaging Role. I apply these to all Exchange Servers. + +## Please review everything +Before using the scripts to configure and/or load anything, you should review them! Do not just execute them. These scripts will change a lot and it will reconfigure a lot on your Skype for Business servers!!! +Don't blame me if something doesn't work as you might expect it. + +## Detailed configuration +The source is the documentation! I know, that sounds typical for a geek... But if you take a closer look at the scripts, you will see a lot of comments and documentation snippets. They should make the settings and a lot of the logic clear. + +Microsoft (MSFT) and the community provide a lot of very good and detailed documentation about Skype and QoS. + +## Content +Here is a quick overview of the content + +### `Client_GPO.ps1` +Create the Skype for Busines related Quality of Services Client Group Policy + +### `Edge_REG.ps1` +Setup the Skype for Business 2015 Edge Server for Quality of Services +Edge Servers are not domain joined, we have to modify the registry instead of using a Group Policy + +### `ExchangeUM_GPO.ps1` +Create the Skype for Busines related Exchange Unified Messaging Quality of Services Group Policy + +### `Server_GPO.ps1` +Create the Skype for Busines related Quality of Services Server Group Policy + +### `Skype_Server_Config.ps1` +Setup the Skype for Business 2015 Server for Quality of Services + +## Signed +There is a signed version of the scripts within the 'signed' directory. The scripts are the same, they are signed with a valid certificate. + +## Support +Are you kidding me? This is free software. Take it, or leave it! + +## Final remarks +You Network Equipment must support QoS End-to-End! + +Teams is not supported (yet). + +Some of the new ports for Skype for Business Online (SfBO) are still missing. I might provide an updated version for them soon. + +Hybrid with Skype for Business Online (SfBO) will work! But if you want to use QoS End-To-End, Fast Track might be required. Ask Microsoft! diff --git a/Powershell/PowerShell-collection/Skype_for_Business/Set-Skype4BProxyUsage.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/Set-Skype4BProxyUsage.ps1 new file mode 100644 index 0000000..ce49e19 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/Set-Skype4BProxyUsage.ps1 @@ -0,0 +1,85 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Skype for Business should use Proxy Server + + .DESCRIPTION + Skype for Business should use Proxy Server to sign in instead of trying a direct connection. + Works with Skype for Business 2015 and 2016 and should work with Lync 1013 as well. + + .EXAMPLE + PS C:\> .\Set-Skype4BProxyUsage.ps1 + + .NOTES + Please note: This is a per user setting! + + SIP is not used between Clients (aka P2P or Cleint to Client). + It wil be used between Client and Server and/or Server and Server. + Media Bypass will be used for RTP media between Clients (when possible) + + .LINK + https://support.microsoft.com/en-us/help/3207112/skype-for-business-should-use-proxy-server-to-sign-in-instead-of-tryin + + .LINK + https://blogs.technet.microsoft.com/uclobby/2016/12/08/enabling-lyncsfb-client-to-use-proxy-server-for-sip-traffic-instead-of-trying-direct-connection/ +#> +[CmdletBinding()] +param () + +$parameters = @{ + Path = 'HKCU:\Software\Microsoft\UCCPlatform\Lync' + Name = 'EnableDetectProxyForAllConnections' + PropertyType = 'DWORD' + Value = '1' + Force = $true + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' +} + +try +{ + $null = (New-ItemProperty @parameters) + Write-Verbose -Message 'New value set.' +} +catch +{ + try + { + $null = (Set-ItemProperty @parameters) + Write-Verbose -Message 'Existing value modified.' + } + catch + { + Write-Warning -Message 'Unable to create/set the value.' + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Skype_for_Business/Test-LyncSRVRecords.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/Test-LyncSRVRecords.ps1 new file mode 100644 index 0000000..eb9e6f8 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/Test-LyncSRVRecords.ps1 @@ -0,0 +1,228 @@ +function Test-LyncSRVRecords +{ + <# + .SYNOPSIS + Check for existing Lync/Skype for Business DNS Records + + .DESCRIPTION + Check for existing Lync/Skype for Business DNS Records + + .PARAMETER DomainName + Domain name to check, e.g. enatec.net + Defaults to the DNS domain of the localhost + + .PARAMETER DNS + Domain Name Server to use. Defaults to the CloudFlare Server 1.1.1.1 + + .EXAMPLE + PS C:\> Test-LyncSRVRecords + + Check for existing Lync/Skype for Business DNS Records for the DNS Domain of the local host + + .EXAMPLE + PS C:\> Test-LyncSRVRecords -DomainName 'contoso.com' + + Check for existing Lync/Skype for Business DNS Records for contoso.com + + .EXAMPLE + PS C:\> Test-LyncSRVRecords -DomainName 'contoso.com' -DNS '8.8.8.8' + + Check for existing Lync/Skype for Business DNS Records for contoso.com on the Google public DNS Server + + .NOTES + Original by J. Hulsmans (@JHulsmans) https://about.me/jonihulsmans - MIT licensed + Refactored and migrated to psobject output instead of Write-Host + + .LINK + https://github.com/JHulsmans/PowerShell/blob/master/DNS/CheckSRVRecord.ps1 + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([psobject])] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [Alias('Domain')] + [string] + $DomainName = ((Get-WmiObject -Class win32_computersystem).Domain), + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [ValidateNotNullOrEmpty()] + [string] + $DNS = '1.1.1.1' + ) + + begin + { + # Definne some defaults + $Type = 'SRV' + $SCT = 'SilentlyContinue' + + # Set a default to prevent Null pointer exceptions, You can use $null here as well if you know what you're doing + $NotFound = 'unknown' + + # Create the new Object + $FinalResult = New-Object -TypeName psobject + } + + process + { + $CnameResult = (Resolve-DnsName -Name sip.$DomainName -Server $DNS -ErrorAction $SCT) + $LyncDiscoverResult = (Resolve-DnsName -Name lyncdiscover.$DomainName -Type A -Server $DNS -ErrorAction $SCT) + $LyncDiscoverResultv6 = (Resolve-DnsName -Name lyncdiscover.$DomainName -Type AAAA -Server $DNS -ErrorAction $SCT) + $FederationResult = (Resolve-DnsName -Name _sipfederationtls._tcp.$DomainName -Type $Type -Server $DNS -ErrorAction $SCT) + $SipTlsResult = (Resolve-DnsName -Name _sip._tls.$DomainName -Type $Type -Server $DNS -ErrorAction $SCT) + + if ($CnameResult) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name SipHost -Value sip.$DomainName + $FinalResult | Add-Member -MemberType NoteProperty -Name Cname -Value $(@(foreach ($result in $CnameResult.namehost) + { + $result + } + )) + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name SipHost -Value $NotFound + $FinalResult | Add-Member -MemberType NoteProperty -Name Cname -Value $NotFound + } + + if ($LyncDiscoverResult) + { + if ($LyncDiscoverResult.Name) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscover -Value ($LyncDiscoverResult.Name | Sort-Object | Get-Unique -OnType) + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscover -Value $NotFound + } + + if ($LyncDiscoverResult.NameHost) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverCname -Value ($LyncDiscoverResult.NameHost | Sort-Object | Get-Unique -OnType) + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverCname -Value $NotFound + } + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscover -Value $NotFound + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverCname -Value $NotFound + } + + # Get the IPv6 entry, if exists + if ($LyncDiscoverResultv6) + { + if ($LyncDiscoverResultv6.Name) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverV6 -Value ($LyncDiscoverResultv6.Name | Sort-Object | Get-Unique -OnType) + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverV6 -Value $NotFound + } + + if ($LyncDiscoverResultv6.NameHost) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverCnameV6 -Value ($LyncDiscoverResultv6.NameHost | Sort-Object | Get-Unique -OnType) + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverCnameV6 -Value $NotFound + } + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverV6 -Value $NotFound + $FinalResult | Add-Member -MemberType NoteProperty -Name LyncDiscoverCnameV6 -Value $NotFound + } + + if ($FederationResult) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name Federation -Value $FederationResult.NameTarget + + if ($FederationResult.NameTarget -like '*.lync.com') + { + $IsOnline = $true + } + else + { + $IsOnline = $null + } + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name Federation -Value $NotFound + $IsOnline = $null + } + + if ($SipTlsResult) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name SipTls -Value $SipTlsResult.NameTarget + + if ($SipTlsResult.NameTarget -like '*.lync.com') + { + $IsOnline = $true + } + else + { + $IsOnline = $null + } + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name SipTls -Value $NotFound + $IsOnline = $null + } + + if ($IsOnline) + { + $FinalResult | Add-Member -MemberType NoteProperty -Name IsOnine -Value $true + } + else + { + $FinalResult | Add-Member -MemberType NoteProperty -Name IsOnine -Value $false + } + } + + end + { + $FinalResult + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Skype_for_Business/readme.md b/Powershell/PowerShell-collection/Skype_for_Business/readme.md new file mode 100644 index 0000000..d7338b1 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/readme.md @@ -0,0 +1,8 @@ +# Legacy Notice + +I no longer run Exchange, Skype for Business, or any other Office Server on Premises. +This is my personal [reaction](https://hochwald.net/microsoft-rolls-back-decision-to-take-away-internal-usage-rights-from-partners/) to the changes that Microsoft [announced](https://hochwald.net/microsoft-is-going-to-kill-internal-use-rights-benefit-for-partners/) for the Internal Use Rights (IUR) program. I know that they decided to reverse that changes and in theory, I could still legally use the software. However, I decided to decommission everything licensed under the terms of the Internal Use Rights (IUR) program. +In my opinion, the community always should have some benefits from the Internal Use Rights (IUR) program and/or Action Pack. Now that I decided to drop out, there will be no more such benefits. + +I will _no longer maintain_ the scripts related to the Microsoft Office (on Premises) servers. They will remain here, but unmaintained. Fork the repository and maintain or extend them if you like to. The [License](https://github.com/jhochwald/PowerShell-collection/blob/master/LICENSE) allows that easily. + diff --git a/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/LICENSE b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/LICENSE b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/rms4bcert.exe b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/rms4bcert.exe new file mode 100644 index 0000000..81d51e3 Binary files /dev/null and b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/rms4bcert.exe differ diff --git a/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/rms4bcert.exe.config b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/rms4bcert.exe.config new file mode 100644 index 0000000..9b81f40 --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/bin/x64/rms4bcert.exe.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/rms4bcert.ps1 b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/rms4bcert.ps1 new file mode 100644 index 0000000..0ff5b1e --- /dev/null +++ b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/rms4bcert.ps1 @@ -0,0 +1,55 @@ +$paramGetChildItem = @{ + Path = 'Cert:\CurrentUser\My' + Recurse = $true + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' +} + +$paramRemoveItem = @{ + ErrorAction = 'SilentlyContinue' + WarningAction = 'SilentlyContinue' + Force = $true + Confirm = $false +} + +Get-ChildItem @paramGetChildItem | Where-Object -FilterScript { + $_.Issuer -like 'CN=Communications Server' +} | Remove-Item @paramRemoveItem + +#region CHANGELOG +<# + Soon +#> +#endregion CHANGELOG + +#region LICENSE +<# + LICENSE: + + Copyright 2018 by enabling Technology - http://enatec.io + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + By using the Software, you agree to the License, Terms and Conditions above! +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER + diff --git a/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/rms4bcert.ps1.psbuild b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/rms4bcert.ps1.psbuild new file mode 100644 index 0000000..fbe5110 Binary files /dev/null and b/Powershell/PowerShell-collection/Skype_for_Business/rms4bcert/rms4bcert.ps1.psbuild differ diff --git a/Powershell/PowerShell-collection/UniFiTooling/readme.md b/Powershell/PowerShell-collection/UniFiTooling/readme.md new file mode 100644 index 0000000..8b6df39 --- /dev/null +++ b/Powershell/PowerShell-collection/UniFiTooling/readme.md @@ -0,0 +1,3 @@ +# UniFiTooling + +New location: [https://github.com/Enatec/UniFiTooling](https://github.com/Enatec/UniFiTooling) diff --git a/Powershell/PowerShell-collection/WSUS/Approve-WSUSDefinitionUpdates.ps1 b/Powershell/PowerShell-collection/WSUS/Approve-WSUSDefinitionUpdates.ps1 new file mode 100644 index 0000000..9e49603 --- /dev/null +++ b/Powershell/PowerShell-collection/WSUS/Approve-WSUSDefinitionUpdates.ps1 @@ -0,0 +1,225 @@ +#requires -Version 3.0 -Modules UpdateServices + +<# + .SYNOPSIS + Approves all Windows Server Update Services (WSUS) definition updates + + .DESCRIPTION + Approves all definition updates to all given Windows Server Update Services (WSUS) Computer Groups + + .PARAMETER Name + Specifies the name of a WSUS server. + + .PARAMETER TargetGroupNames + Specifies the name(s) of the WSUS computer target group(s) for which to run this cmdlet. + + .EXAMPLE + PS C:\> Approve-WSUSDefinitionUpdates -TargetGroupNames 'All Computers' + + Approve Definition Updates to the 'All Computers' Group + + .EXAMPLE + PS C:\> Approve-WSUSDefinitionUpdates -Name 'mycdc01' -TargetGroupNames 'All Computers' + + Approves all definition updates to the 'All Computers' Group on the Windows Server Update Services (WSUS) Server 'mycdc01' + + .EXAMPLE + PS C:\> Approve-WSUSDefinitionUpdates -TargetGroupNames 'All Computers' -WhatfIf + + Simmulate the approval of all definition updates to the 'All Computers' Windows Server Update Services (WSUS) Group + + .EXAMPLE + PS C:\> Approve-WSUSDefinitionUpdates -TargetGroupNames 'Pilot Servers','Pilot Workstations' + + Approves all definition updates to the 'Pilot Servers' and 'Pilot Workstations' Windows Server Update Services (WSUS) groups + + .NOTES + Initial beta Version +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('WSUSServer')] + [string] + $Name = $null, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 2, + HelpMessage = 'Specifies the name(s) of the WSUS computer target group(s) for which to run this cmdlet.')] + [ValidateNotNullOrEmpty()] + [Alias('InstallGroups')] + [string[]] + $TargetGroupNames +) + +begin +{ + try + { + # Set the Defaults + $paramGetWsusServer = @{ + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + + if ($Name) + { + Write-Verbose -Message ('Use {0} as WSUS Server' -f $Name) + + # Add the Name field with the given value to the Hashtable (Command Splat) + $paramGetWsusServer['Name'] = $Name + } + + $WSUS = (Get-WsusServer @paramGetWsusServer) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about the error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff for troubleshooting + $info | Out-String | Write-Verbose + + # Thow the error and go... + Write-Error -Message "$info.Exception" -ErrorAction Stop + + # This is a point the code should never reach (You told PowerShell to Ignore the ErrorAction above!) + break + + # OK, now we have reached a point the we would never, never ever, see + exit 1 + } + + $DefinitionUpdates = $null + $DefinitionUpdates = $WSUS.GetUpdateClassifications() | Where-Object -FilterScript { + $_.Title -eq 'Definition Updates' + } + + if (-not $DefinitionUpdates) + { + Write-Error -Message 'No Definition Updates found!' -ErrorAction Stop + + break + + exit 1 + } + + $AllDefinitionUpdates = $null + $AllDefinitionUpdates = $DefinitionUpdates.GetUpdates() | Where-Object -FilterScript { + ($_.Title -like 'Definition Update for Microsoft Security Essentials*') -or ($_.Title -like 'Update for Windows Defender Antivirus antimalware platforms*') -or ($_.Title -like 'Definition Update for Windows Defender Antivirus*') + } + + if (-not $AllDefinitionUpdates) + { + # Thow the error and go... + Write-Error -Message 'No Definition Updates found!!!' -ErrorAction Stop + + # This is a point the code should never reach (You told PowerShell to Ignore the ErrorAction above!) + break + + # OK, now we have reached a point the we would never, never ever, see + exit 1 + } + +} + +process +{ + # Loop over all Updates + foreach ($UpdateID in $AllDefinitionUpdates.Id.UpdateId.Guid) + { + # Loop over all Goups + foreach ($TargetGroupName in $TargetGroupNames) + { + try + { + $paramGetWsusUpdate = @{ + UpdateId = $UpdateID + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + $paramApproveWsusUpdate = @{ + Action = 'Install' + TargetGroupName = $TargetGroupName + ErrorAction = 'Stop' + WarningAction = 'SilentlyContinue' + } + if ($pscmdlet.ShouldProcess("$UpdateID to $TargetGroupName", 'Approve')) + { + $null = (Get-WsusUpdate @paramGetWsusUpdate | Approve-WsusUpdate @paramApproveWsusUpdate) + } + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about the error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff for troubleshooting + $info | Out-String | Write-Verbose + + # A simple warning is OK here + Write-Warning -Message "$info.Exception" -WarningAction Continue -ErrorAction Continue + } + } + } +} + +end +{ + Write-Verbose -Message 'Done' +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/WSUS/Approve-WSUSLicenseAgreementAcceptance.ps1 b/Powershell/PowerShell-collection/WSUS/Approve-WSUSLicenseAgreementAcceptance.ps1 new file mode 100644 index 0000000..17967fb --- /dev/null +++ b/Powershell/PowerShell-collection/WSUS/Approve-WSUSLicenseAgreementAcceptance.ps1 @@ -0,0 +1,154 @@ +#requires -Version 3.0 -Modules UpdateServices + +<# + .SYNOPSIS + Accept License Agreements + + .DESCRIPTION + Accept License Agreements for all Windows Server Update Services (WSUS) Updates + + .PARAMETER Name + Specifies the name of a WSUS server. + + .EXAMPLE + PS C:\> Approve-WSUSLicenseAgreementAcceptance -Name 'mycdc01' + + Accept License Agreements on the WSUS Server 'mycdc01' + + .EXAMPLE + PS C:\> Approve-WSUSLicenseAgreementAcceptance + + Accept License Agreements + + .NOTES + Initial beta Version +#> +[CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 1)] + [Alias('WSUSServer')] + [string] + $Name = $null +) + +begin +{ + try + { + # Set the Defaults + $paramGetWsusServer = @{ + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + + if ($Name) + { + Write-Verbose -Message ('Use {0} as WSUS Server' -f $Name) + + # Add the Name field with the given value to the Hashtable (Command Splat) + $paramGetWsusServer['Name'] = $Name + } + + $WSUS = (Get-WsusServer @paramGetWsusServer) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # Retrieve information about the error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Do some verbose stuff for troubleshooting + $info | Out-String | Write-Verbose + + # Thow the error and go... + Write-Error -Message "$info.Exception" -ErrorAction Stop + + # This is a point the code should never reach (You told PowerShell to Ignore the ErrorAction above!) + break + + # OK, now we have reached a point the we would never, never ever, see + exit 1 + } + + $unapprovedUpdates = $null + $unapprovedUpdates = $WSUS.getupdates() | Where-Object -FilterScript { + $_.isdeclined -ne $true + } + + $license = $null + if ($unapprovedUpdates) + { + $license = $unapprovedUpdates | Where-Object -FilterScript { + $_.RequiresLicenseAgreementAcceptance + } + } + else + { + Write-Verbose -Message 'Nothing left todo.' + } +} + +process +{ + if ($license) + { + if ($pscmdlet.ShouldProcess("$license", 'Accept License Agreement')) + { + $license | ForEach-Object -Process { + $_.AcceptLicenseAgreement() + } + } + } + else + { + Write-Verbose -Message 'Nothing left todo...' + } +} + +end +{ + Write-Verbose -Message 'Done' +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/WSUS/LICENSE b/Powershell/PowerShell-collection/WSUS/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/WSUS/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/WSUS/README.md b/Powershell/PowerShell-collection/WSUS/README.md new file mode 100644 index 0000000..d7338b1 --- /dev/null +++ b/Powershell/PowerShell-collection/WSUS/README.md @@ -0,0 +1,8 @@ +# Legacy Notice + +I no longer run Exchange, Skype for Business, or any other Office Server on Premises. +This is my personal [reaction](https://hochwald.net/microsoft-rolls-back-decision-to-take-away-internal-usage-rights-from-partners/) to the changes that Microsoft [announced](https://hochwald.net/microsoft-is-going-to-kill-internal-use-rights-benefit-for-partners/) for the Internal Use Rights (IUR) program. I know that they decided to reverse that changes and in theory, I could still legally use the software. However, I decided to decommission everything licensed under the terms of the Internal Use Rights (IUR) program. +In my opinion, the community always should have some benefits from the Internal Use Rights (IUR) program and/or Action Pack. Now that I decided to drop out, there will be no more such benefits. + +I will _no longer maintain_ the scripts related to the Microsoft Office (on Premises) servers. They will remain here, but unmaintained. Fork the repository and maintain or extend them if you like to. The [License](https://github.com/jhochwald/PowerShell-collection/blob/master/LICENSE) allows that easily. + diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/Autounattend_Legacy.xml b/Powershell/PowerShell-collection/Windows10-Bootstrapper/Autounattend_Legacy.xml new file mode 100644 index 0000000..6892393 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/Autounattend_Legacy.xml @@ -0,0 +1,185 @@ + + + + + + en-US + + 047:00000407 + en-US + de-DE + en-US + + + + + + + 1 + Primary + 100 + + + true + 2 + Primary + + + + + true + NTFS + + 1 + 1 + 0x27 + + + true + NTFS + + C + 2 + 2 + + + 0 + true + + OnError + + + + + 0 + 2 + + OnError + + + /image/name + Windows 10 Enterprise + + + + + + true + + + OnError + + + + + + + + + + C:\Drivers + + + + C:\Intel + + + + C:\SWSetup + + + + + + + true + + + W. Europe Standard Time + enabling Technology + enabling Technology + + + 047:00000407 + en-US + de-DE + + + + + 1 + Set Execution Policy 64 Bit + C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Set-ExecutionPolicy -ExecutionPolicy Bypass -Force -ErrorAction SilentlyContinue" + Never + + + 2 + Set Execution Policy 32 Bit + C:\Windows\syswow64\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Set-ExecutionPolicy -ExecutionPolicy Bypass -Force -ErrorAction SilentlyContinue" + Never + + + + + 1 + + + + + + true + true + true + true + true + 3 + true + true + false + + + + + Audit + false + + + + + + + + + 1 + powershell.exe -noprofile -File c:\windows\setup\scripts\BootOOBE.ps1 + Never + Prepare OOBE + + + + + + diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/Autounattend_UEFI.xml b/Powershell/PowerShell-collection/Windows10-Bootstrapper/Autounattend_UEFI.xml new file mode 100644 index 0000000..d917b75 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/Autounattend_UEFI.xml @@ -0,0 +1,202 @@ + + + + + + en-US + + 047:00000407 + en-US + de-DE + en-US + + + + + 0 + true + + + 1 + Primary + 300 + + + 2 + EFI + 100 + + + 3 + MSR + 128 + + + 4 + Primary + true + + + + + 1 + 1 + + NTFS + DE94BBA4-06D1-4D40-A16A-BFD50179D6AC + + + 2 + 2 + + FAT32 + + + 3 + 3 + + + 4 + 4 + + C + NTFS + + + + + + + + 0 + 4 + + OnError + + + /image/name + Windows 10 Enterprise + + + + + + true + + + OnError + + + + + + + + + + C:\Drivers + + + + C:\Intel + + + + C:\SWSetup + + + + + + + true + + + W. Europe Standard Time + enabling Technology + enabling Technology + + + 047:00000407 + en-US + de-DE + + + + + 1 + Set Execution Policy 64 Bit + C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Set-ExecutionPolicy -ExecutionPolicy Bypass -Force -ErrorAction SilentlyContinue" + Never + + + 2 + Set Execution Policy 32 Bit + C:\Windows\syswow64\WindowsPowerShell\v1.0\powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "Set-ExecutionPolicy -ExecutionPolicy Bypass -Force -ErrorAction SilentlyContinue" + Never + + + + + 1 + + + + + + true + true + true + true + true + 3 + true + true + false + + + + + Audit + false + + + + + + + + + 1 + powershell.exe -noprofile -File c:\windows\setup\scripts\BootOOBE.ps1 + Never + Prepare OOBE + + + + + + diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/ENATEC.ppkg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/ENATEC.ppkg new file mode 100644 index 0000000..f5e0e93 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/ENATEC.ppkg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/ENSHARED.ppkg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/ENSHARED.ppkg new file mode 100644 index 0000000..ff2414b Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/ENSHARED.ppkg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/LICENSE b/Powershell/PowerShell-collection/Windows10-Bootstrapper/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/Readme.md b/Powershell/PowerShell-collection/Windows10-Bootstrapper/Readme.md new file mode 100644 index 0000000..b1a3a7b --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/Readme.md @@ -0,0 +1,123 @@ +# Windows 10 Client System Bootstrapper + +enabling Technology progressive OS deployment (ETPOSD) + +Client System Bootstrapper for Windows 10 Enterprise Installations + +**This will be moved to a separate repository soon.** + +## What is this? + +It is part of an internal enabling Technology Project. + +We had to deploy a lot of new clients and with this approach we just had to provide an ISO Image/USB-Stick to get that going. + +After the installation, you can use the pre deployed PowerShell scripts to upload the AutoPilot Info to your Microsoft 365 Tenant, that will speed up future installations! + +## How-To + +If you apply _all_ the Files to you Windows 10 ISO file and create a bootable image from it, you will have a Jump started Windows 10 Image. + +Rename the `Autounattend_Legacy.xml` or `Autounattend_UEFI.xml` file to `Autounattend.xml` if you want to have a fully unattend installation until the login to your Microsoft 365 tenant (See the hints, notes, and remarks below)! + +It will do a plain installation and enroll to AzureAD and Intune (AutoPilot). + +When the Installation is finished, login with a Microsoft 365 user that have Admin permissions on the local System and execute `c:\install\start.cmd`. + +The `c:\install\start.cmd` file is a wrapper that will do all the magic in the background for you. + +Please remember to download the Office 365 Click-2-Run sources before you start the installation! You can download them before you create your install image, this will speed up the process and you don't have to download the sources for each client system! + +The Office Suite will be removed soon from the scripts! We use Intune to deploy the Office 365 Suite and Microsoft 365 to activate it. + +## Please Note + +1st of all: Please review the `c:\install\start.cmd`! Skip the parts that you don't want to be applied. We are not Batch experts, as you might see very quickly. + +We decided to stay with the Batch, because this was in use way before we established this new approach and all the users knew about the directory and this file! + +1. Please review all the XML, Batch, and PowerShell Files before you apply them! +2. Download Office 365 (See the Batch) - Review the XML +3. Download the Lenovo specific files (Removed to prevent any kind of licensing issues) +4. Review `\srources\$OEM$\$$\System32\sysprep\unattend.xml` very careful +5. The `\srources\$OEM$\$$\System32\Autopilot\AutopilotConfigurationFile.json` will enroll your system to Intune in our test Tenant - Modify or remove this file! +6. The `\ENATEC.ppkg` file will bind your system to AzureAD in our test Tenant - Replace or remove this file! +7. The `\ENATEC.ppkg` file will rename your system - Replace or remove this file! +8. Replace the KMS Server **kms.enatec.net** with your own KMS server. You can also use Microsoft 365 to activate your Microsoft Windows 10 and/or your Office 365 Office Suite, and that is recommended for future use. + +### Office 365 - Click-to-Run + +The XML is still using KMS to activate the Office Suite! You might want to change this to met you own licensing. We will change everything towards online activation in the future! + +## Change-log + +Public Change-log (no longer maintained): + +- 1.4.7: Add KMS Ping checks for Windows and Office activation +- 1.4.6: Test Release - ALL +- 1.4.5: Change the logging and add errorlevel to all enties - JHO +- 1.4.4: Rewrite this Wrapper Batch file to make it more robust - JHO +- 1.4.3: Tweak the BitLocker part and add auto upload to AzureAD/Intune - JHO +- 1.4.2: Add Storage Sense part - PDU +- 1.4.1: Test Release - ALL +- 1.4.0: Bugfix Release (Error handling) - PDU +- 1.3.12: Test Release - ALL +- 1.3.11: Hardware Vendor handling changed - PDU +- 1.3.10: Hardware Vendor handling online test - JHO +- 1.3.9: Automated Driver installer added - PDU +- 1.3.8: WinGet added - JHO +- 1.3.7: Test with Windows 10 Enterprise Release 2009 - ALL +- 1.3.6: Add the BitLocker part - JHO +- 1.3.5: Remove the Office sources after installation - PDU +- 1.3.4: Change the Autoupdate handling - PDU +- 1.3.3: Remove the WinGet Test - JHO +- 1.3.2: Test Release - ALL +- 1.3.1: Add a WinGet Test - PDU +- 1.3.0: Test Release - ALL +- 1.2.6: Removed all Batch Modules - JHO +- 1.2.5: Test Release - ALL +- 1.2.4: Bugfix for the Modules - JHO +- 1.2.3: Test Release - ALL +- 1.2.2: Removed AutoPilot automated Upload due to login issues - JHO +- 1.2.1: Automated AutoPilot info upload to Intune introduced - JHO +- 1.2.0: Rewrite the complete Wrapper: Use Batch Modules - PDU +- 1.1.3: Test Release - ALL +- 1.1.2: Remove the WiFi Setup - JHO +- 1.1.1: Remove the Ping and VPN Test - JHO +- 1.1.0: Remove the local Domain login - JHO +- 1.0.8: Test Release - ALL +- 1.0.7: Rename the Log File (Now the Module Name) - RBU +- 1.0.6: Change the Log format (Add Time Stamps) - RDU +- 1.0.5: Change Naming convention (Removed here, no in the Provisioning package) - JHO +- 1.0.4: Test Release - ALL +- 1.0.3: Add Intune/AzureAD Provisioning package - JHO +- 1.0.2: Test Release - ALL +- 1.0.1: Hardcoded AutoPilot Info added - JHO +- 1.0.0: Changed to this Wrapper - JHO +- Older: Internal test Releases - ALL + +Changes for the scripts should be documented in the scripts file itself. + +## License + +### BSD 3-Clause License + +Copyright (c) 2021, enabling Technology - All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +**THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.** + +## Disclaimer + +- Use at your own risk, etc. +- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind +- This is a third-party Software +- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way +- The Software is not supported by Microsoft Corp (MSFT) +- By using the Software, you agree to the License, Terms, and any Conditions declared and described above +- If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/autorun.inf b/Powershell/PowerShell-collection/Windows10-Bootstrapper/autorun.inf new file mode 100644 index 0000000..e69de29 diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/00-SetNtpServerAndTime/SetNtpServerAndTime.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/00-SetNtpServerAndTime/SetNtpServerAndTime.cmd new file mode 100644 index 0000000..3ae0922 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/00-SetNtpServerAndTime/SetNtpServerAndTime.cmd @@ -0,0 +1,90 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Set NTP-Server and Time +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:SetNtpServerAndTime +TITLE SetNtpServerAndTime +SET Module=SetNtpServerAndTime +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +%SystemRoot%\System32\net.exe stop w32time >nul 2>&1 +%SystemRoot%\System32\w32tm.exe /config /syncfromflags:manual /manualpeerlist:"0.de.pool.ntp.org 1.de.pool.ntp.org 2.de.pool.ntp.org 3.de.pool.ntp.org" >nul 2>&1 +%SystemRoot%\System32\net.exe start w32time >nul 2>&1 +%SystemRoot%\System32\sc.exe config w32time start= auto >nul 2>&1 +%SystemRoot%\System32\w32tm.exe /resync /force >nul 2>&1 + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/01-SetPowerPlanToHighPerformance/SetPowerPlanToHighPerformance.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/01-SetPowerPlanToHighPerformance/SetPowerPlanToHighPerformance.cmd new file mode 100644 index 0000000..61208f0 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/01-SetPowerPlanToHighPerformance/SetPowerPlanToHighPerformance.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Set Powerplan to High Performance +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:SetPowerPlanToHighPerformance +TITLE SetPowerPlanToHighPerformance +SET Module=SetPowerPlanToHighPerformance +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Set Power Plan to High Performance +ECHO %TIME:~0,8% Set Power Plan to High Performance >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "c:\scripts\PowerShell\Set-PowerPlanToHighPerformance.ps1" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/02-DisableTheNetworkDiscoveryPromptWindow/DisableTheNetworkDiscoveryPromptWindow.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/02-DisableTheNetworkDiscoveryPromptWindow/DisableTheNetworkDiscoveryPromptWindow.cmd new file mode 100644 index 0000000..f55316b --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/02-DisableTheNetworkDiscoveryPromptWindow/DisableTheNetworkDiscoveryPromptWindow.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable the Network Discovery Prompt Window +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableTheNetworkDiscoveryPromptWindow +TITLE DisableTheNetworkDiscoveryPromptWindow +SET Module=DisableTheNetworkDiscoveryPromptWindow +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable the network discovery prompt window +ECHO %TIME:~0,8% Disable the network discovery prompt window >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKLM\System\CurrentControlSet\Control\Network\NewNetworkWindowOff" /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/03-NoBackgroundImageAtTheLogonPage/NoBackgroundImageAtTheLogonPage.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/03-NoBackgroundImageAtTheLogonPage/NoBackgroundImageAtTheLogonPage.cmd new file mode 100644 index 0000000..4c533fa --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/03-NoBackgroundImageAtTheLogonPage/NoBackgroundImageAtTheLogonPage.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: NoBackgroundImageAtTheLogonPage +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:NoBackgroundImageAtTheLogonPage +TITLE NoBackgroundImageAtTheLogonPage +SET Module=NoBackgroundImageAtTheLogonPage +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO No Background Image at the Logon Page +ECHO %TIME:~0,8% No Background Image at the Logon Page >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\System" /v DisableLogonBackgroundImage /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/04-IncreaseTaskbarTransparencyLevel/IncreaseTaskbarTransparencyLevel.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/04-IncreaseTaskbarTransparencyLevel/IncreaseTaskbarTransparencyLevel.cmd new file mode 100644 index 0000000..9835a2b --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/04-IncreaseTaskbarTransparencyLevel/IncreaseTaskbarTransparencyLevel.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Increase Taskbar Transparency Level +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:IncreaseTaskbarTransparencyLevel +TITLE IncreaseTaskbarTransparencyLevel +SET Module=IncreaseTaskbarTransparencyLevel +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Increase Taskbar Transparency Level +ECHO %TIME:~0,8% Increase Taskbar Transparency Level >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v UseOLEDTaskbarTransparency /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/05-QuickShutdown/QuickShutdown.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/05-QuickShutdown/QuickShutdown.cmd new file mode 100644 index 0000000..74f07a3 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/05-QuickShutdown/QuickShutdown.cmd @@ -0,0 +1,94 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Quick Shutdown +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:QuickShutdown +TITLE QuickShutdown +SET Module=QuickShutdown +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Quick Shutdown +ECHO %TIME:~0,8% Quick Shutdown >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control" /v WaitToKillServiceTimeout /t REG_SZ /d 1000 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO Set wait to kill service timeout to 1000 +ECHO %TIME:~0,8% Set wait to kill service timeout to 1000 >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control" /v WaitToKillServiceTimeout /t REG_SZ /d 1000 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/07-DisableFirstTimeSignInAnimation/DisableFirstTimeSignInAnimation.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/07-DisableFirstTimeSignInAnimation/DisableFirstTimeSignInAnimation.cmd new file mode 100644 index 0000000..adbfdea --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/07-DisableFirstTimeSignInAnimation/DisableFirstTimeSignInAnimation.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable First Time Sign In Animation +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableFirstTimeSignInAnimation +TITLE DisableFirstTimeSignInAnimation +SET Module=DisableFirstTimeSignInAnimation +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable First Time Sign-in Animation +ECHO %TIME:~0,8% Disable First Time Sign-in Animation >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Policies\System" /v EnableFirstLogonAnimation /t REG_DWORD /d 0 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/08-DisableTheLockScreen/DisableTheLockScreen.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/08-DisableTheLockScreen/DisableTheLockScreen.cmd new file mode 100644 index 0000000..bf46267 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/08-DisableTheLockScreen/DisableTheLockScreen.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable The Lock Screen +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableTheLockScreen +TITLE DisableTheLockScreen +SET Module=DisableTheLockScreen +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable the Lock Screen +ECHO %TIME:~0,8% Disable the Lock Screen >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization" /v NoLockScreen /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/09-TurnOffFastStartup/TurnOffFastStartup.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/09-TurnOffFastStartup/TurnOffFastStartup.cmd new file mode 100644 index 0000000..49b6ed4 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/09-TurnOffFastStartup/TurnOffFastStartup.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Turn Off Fast Startup +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:TurnOffFastStartup +TITLE TurnOffFastStartup +SET Module=TurnOffFastStartup +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Turn off Fast Startup +ECHO %TIME:~0,8% Turn off Fast Startup >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Power" /v HiberbootEnabled /t REG_DWORD /d 0 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/10-DisablePrivacySettingsExperienceAtSignIn/DisablePrivacySettingsExperienceAtSignIn.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/10-DisablePrivacySettingsExperienceAtSignIn/DisablePrivacySettingsExperienceAtSignIn.cmd new file mode 100644 index 0000000..dc84e6b --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/10-DisablePrivacySettingsExperienceAtSignIn/DisablePrivacySettingsExperienceAtSignIn.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable Privacy Settings Experience At Sign In +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisablePrivacySettingsExperienceAtSignIn +TITLE DisablePrivacySettingsExperienceAtSignIn +SET Module=DisablePrivacySettingsExperienceAtSignIn +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable Privacy Settings Experience at Sign-in +ECHO %TIME:~0,8% Disable Privacy Settings Experience at Sign-in >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\OOBE" /v DisablePrivacyExperience /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/11-DisableTelemetry/DisableTelemetry.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/11-DisableTelemetry/DisableTelemetry.cmd new file mode 100644 index 0000000..d606ac4 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/11-DisableTelemetry/DisableTelemetry.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable Telemetry +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableTelemetry +TITLE DisableTelemetry +SET Module=DisableTelemetry +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable Telemetry +ECHO %TIME:~0,8% Disable Telemetry >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\DataCollection" /v AllowTelemetry /t REG_DWORD /d 0 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/12-AllowMicrosoftUpdatesForOtherProducts/AllowMicrosoftUpdatesForOtherProducts.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/12-AllowMicrosoftUpdatesForOtherProducts/AllowMicrosoftUpdatesForOtherProducts.cmd new file mode 100644 index 0000000..e19b297 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/12-AllowMicrosoftUpdatesForOtherProducts/AllowMicrosoftUpdatesForOtherProducts.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Allow Microsoft Updates For Other Products +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:AllowMicrosoftUpdatesForOtherProducts +TITLE AllowMicrosoftUpdatesForOtherProducts +SET Module=AllowMicrosoftUpdatesForOtherProducts +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Allow Microsoft Updates for other products +ECHO %TIME:~0,8% Allow Microsoft Updates for other products >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\WindowsUpdate\Services\7971f918-a847-4430-9279-4a52d1efe18d" /v RegisteredWithAU /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/13-UnnecessarilyWritingOnSSDWillShortenTheLifetime/UnnecessarilyWritingOnSSDWillShortenTheLifetime.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/13-UnnecessarilyWritingOnSSDWillShortenTheLifetime/UnnecessarilyWritingOnSSDWillShortenTheLifetime.cmd new file mode 100644 index 0000000..d494bd7 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/13-UnnecessarilyWritingOnSSDWillShortenTheLifetime/UnnecessarilyWritingOnSSDWillShortenTheLifetime.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Unnecessarily Writing On SSD Will Shorten The Lifetime +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:UnnecessarilyWritingOnSSDWillShortenTheLifetime +TITLE UnnecessarilyWritingOnSSDWillShortenTheLifetime +SET Module=UnnecessarilyWritingOnSSDWillShortenTheLifetime +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Unnecessarily writing on SSD will shorten the lifetime +ECHO %TIME:~0,8% Unnecessarily writing on SSD will shorten the lifetime >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem" /v NtfsDisableLastAccessUpdate /t REG_DWORD /d 80000001 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/14-DisableAutoRunForAllVolumes/DisableAutoRunForAllVolumes.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/14-DisableAutoRunForAllVolumes/DisableAutoRunForAllVolumes.cmd new file mode 100644 index 0000000..1ee4e2f --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/14-DisableAutoRunForAllVolumes/DisableAutoRunForAllVolumes.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable Auto Run For All Volumes +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableAutoRunForAllVolumes +TITLE DisableAutoRunForAllVolumes +SET Module=DisableAutoRunForAllVolumes +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable Auto Run for all volumes +ECHO %TIME:~0,8% Disable Auto Run for all volumes >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Explorer" /v NoAutoplayfornonVolume /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/15-DisplayDetailedInformationInDeviceManager/DisplayDetailedInformationInDeviceManager.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/15-DisplayDetailedInformationInDeviceManager/DisplayDetailedInformationInDeviceManager.cmd new file mode 100644 index 0000000..edd992f --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/15-DisplayDetailedInformationInDeviceManager/DisplayDetailedInformationInDeviceManager.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Display Detailed Information In Device Manager +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisplayDetailedInformationInDeviceManager +TITLE DisplayDetailedInformationInDeviceManager +SET Module=DisplayDetailedInformationInDeviceManager +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Display detailed information in Device Manager +ECHO %TIME:~0,8% Display detailed information in Device Manager >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment" /v "DEVMGR_SHOW_DETAILS" /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/16-DisableEdgeFirstRun/DisableEdgeFirstRun.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/16-DisableEdgeFirstRun/DisableEdgeFirstRun.cmd new file mode 100644 index 0000000..6135271 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/16-DisableEdgeFirstRun/DisableEdgeFirstRun.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable Edge First Run +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableEdgeFirstRun +TITLE DisableEdgeFirstRun +SET Module=DisableEdgeFirstRun +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable Edge First Run +ECHO %TIME:~0,8% Disable Edge First Run >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\MicrosoftEdge\Main" /v PreventFirstRunPage /t REG_DWORD /d 1 /reg:64 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/17-DisableEdgePrelaunch/DisableEdgePrelaunch.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/17-DisableEdgePrelaunch/DisableEdgePrelaunch.cmd new file mode 100644 index 0000000..9ebf13f --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/17-DisableEdgePrelaunch/DisableEdgePrelaunch.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable Edge Prelaunch +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableEdgePrelaunch +TITLE DisableEdgePrelaunch +SET Module=DisableEdgePrelaunch +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable Edge Prelaunch +ECHO %TIME:~0,8% Disable Edge Prelaunch >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\MicrosoftEdge\Main" /v AllowPrelaunch /t REG_DWORD /d 0 /reg:64 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/18-DisableEdgeTabPreloading/DisableEdgeTabPreloading.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/18-DisableEdgeTabPreloading/DisableEdgeTabPreloading.cmd new file mode 100644 index 0000000..0851564 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/18-DisableEdgeTabPreloading/DisableEdgeTabPreloading.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Disable Edge Tab Pre loading +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DisableEdgeTabPreloading +TITLE DisableEdgeTabPreloading +SET Module=DisableEdgeTabPreloading +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Disable Edge Tab Preloading +ECHO %TIME:~0,8% Disable Edge Tab Preloading >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\MicrosoftEdge\TabPreloader" /v AllowTabPreloading /t REG_DWORD /d 0 /reg:64 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/19-EnableRemotePowerShell/EnableRemotePowerShell.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/19-EnableRemotePowerShell/EnableRemotePowerShell.cmd new file mode 100644 index 0000000..fd9acc3 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/19-EnableRemotePowerShell/EnableRemotePowerShell.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Enable Remote PowerShell +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:EnableRemotePowerShell +TITLE EnableRemotePowerShell +SET Module=EnableRemotePowerShell +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Enable Remote PowerShell +ECHO %TIME:~0,8% Enable Remote PowerShell >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "Enable-PSRemoting -SkipNetworkProfileCheck -Force -Confirm:$false -ErrorAction Continue" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/20-CreatePowerShellProfiles/CreatePowerShellProfiles.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/20-CreatePowerShellProfiles/CreatePowerShellProfiles.cmd new file mode 100644 index 0000000..52ddf3a --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/20-CreatePowerShellProfiles/CreatePowerShellProfiles.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Create PowerShell Profiles +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:CreatePowerShellProfiles +TITLE CreatePowerShellProfiles +SET Module=CreatePowerShellProfiles +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Create plain PowerShell Profiles +ECHO %TIME:~0,8% Create plain PowerShell Profiles >>%logfile_setup% +start /MIN /WAIT "CleanupStockApps" %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "C:\scripts\PowerShell\New-PowerShellProfiles.ps1" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/21-InstallingChocolatey/InstallingChocolatey.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/21-InstallingChocolatey/InstallingChocolatey.cmd new file mode 100644 index 0000000..1be7ffa --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/21-InstallingChocolatey/InstallingChocolatey.cmd @@ -0,0 +1,91 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Installing Chocolatey +:: Version 1.0.2 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:InstallingChocolatey +TITLE InstallingChocolatey +SET Module=InstallingChocolatey +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Installing Chocolatey +ECHO %TIME:~0,8% Installing Chocolatey >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Install-Choco.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: 1.0.1: Fix Typo +:: 1.0.2: Moved the installation to a dedicated PowerShell Script +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/22-AddNuGetPackageSource/AddNuGetPackageSource.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/22-AddNuGetPackageSource/AddNuGetPackageSource.cmd new file mode 100644 index 0000000..171394e --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/22-AddNuGetPackageSource/AddNuGetPackageSource.cmd @@ -0,0 +1,94 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Add NuGet Package Source +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:AddNuGetPackageSource +TITLE AddNuGetPackageSource +SET Module=AddNuGetPackageSource +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Add NuGet Package Source +ECHO %TIME:~0,8% Add NuGet Package Source >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(Install-PackageProvider -Name NuGet -Force -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO Register Nuget Repository +ECHO %TIME:~0,8% Register Nuget Repository >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(Register-PackageSource -Name Nuget -Location 'http://www.nuget.org/api/v2' -ProviderName Nuget -Trusted -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/24-ConfiguresWindowsRemoteManagement/ConfiguresWindowsRemoteManagement.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/24-ConfiguresWindowsRemoteManagement/ConfiguresWindowsRemoteManagement.cmd new file mode 100644 index 0000000..b20206e --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/24-ConfiguresWindowsRemoteManagement/ConfiguresWindowsRemoteManagement.cmd @@ -0,0 +1,94 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Configures Windows Remote Management +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:ConfiguresWindowsRemoteManagement +TITLE ConfiguresWindowsRemoteManagement +SET Module=ConfiguresWindowsRemoteManagement +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Configures Windows Remote Management +ECHO %TIME:~0,8% Configures Windows Remote Management >>%logfile_setup% +start /MIN /WAIT "Configures Windows Remote Management (WinRM)" cmd /c winrm quickconfig -force -quiet >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO Allow Basic authentication Windows Remote Management +ECHO %TIME:~0,8% Allow Basic authentication Windows Remote Management >>%logfile_setup% +start /MIN /WAIT "Allow Basic authentication Windows Remote Management (WinRM)" cmd /c winrm set winrm/config/client/auth @{Basic="true"} >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/26-SetPowerConfigProfile/SetPowerConfigProfile.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/26-SetPowerConfigProfile/SetPowerConfigProfile.cmd new file mode 100644 index 0000000..315f423 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/26-SetPowerConfigProfile/SetPowerConfigProfile.cmd @@ -0,0 +1,94 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Set Power Config Profile +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:SetPowerConfigProfile +TITLE SetPowerConfigProfile +SET Module=SetPowerConfigProfile +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Set Power Config profile +ECHO %TIME:~0,8% Set Power Config profile >>%logfile_setup% +start /MIN /WAIT "Set Power Config profile" %SystemRoot%\system32\powercfg.exe -setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO Change monitor timeout +ECHO %TIME:~0,8% Change monitor timeout >>%logfile_setup% +start /MIN /WAIT "Change monitor timeout" %SystemRoot%\system32\powercfg.exe -Change -monitor-timeout-ac 10 >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/28-CleanupWindows10StockApps/CleanupWindows10StockApps.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/28-CleanupWindows10StockApps/CleanupWindows10StockApps.cmd new file mode 100644 index 0000000..4c0d41d --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/28-CleanupWindows10StockApps/CleanupWindows10StockApps.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: CleanupWindows10StockApps +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:CleanupWindows10StockApps +TITLE CleanupWindows10StockApps +SET Module=CleanupWindows10StockApps +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Cleanup Windows 10 Stock Apps +ECHO %TIME:~0,8% Cleanup Windows 10 Stock Apps >>%logfile_setup% +start /MIN /WAIT "CleanupStockApps" %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "C:\scripts\PowerShell\Cleanup_StockApps.ps1" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/29-BootstrapTheWindows10System/BootstrapTheWindows10System.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/29-BootstrapTheWindows10System/BootstrapTheWindows10System.cmd new file mode 100644 index 0000000..ae2912b --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/29-BootstrapTheWindows10System/BootstrapTheWindows10System.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Bootstrap The Windows 10 Client System +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:BootstrapTheWindows10System +TITLE BootstrapTheWindows10System +SET Module=BootstrapTheWindows10System +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Bootstrap the Windows 10 System +ECHO %TIME:~0,8% Bootstrap the Windows 10 System >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Invoke-BootstrapSystem.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/31-AllowPingAndRemoteDesktop/AllowPingAndRemoteDesktop.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/31-AllowPingAndRemoteDesktop/AllowPingAndRemoteDesktop.cmd new file mode 100644 index 0000000..ee476da --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/31-AllowPingAndRemoteDesktop/AllowPingAndRemoteDesktop.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Allow Ping And Remote Desktop +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:AllowPingAndRemoteDesktop +TITLE AllowPingAndRemoteDesktop +SET Module=AllowPingAndRemoteDesktop +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Allow Ping and RemoteDesktop +ECHO %TIME:~0,8% Allow Ping and RemoteDesktop >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Set-AllowPingAndRemoteDesktop.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/32-SaveSystemImageInfo/SaveSystemImageInfo.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/32-SaveSystemImageInfo/SaveSystemImageInfo.cmd new file mode 100644 index 0000000..6e6a66e --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/32-SaveSystemImageInfo/SaveSystemImageInfo.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Save System Image Info +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:SaveSystemImageInfo +TITLE SaveSystemImageInfo +SET Module=SaveSystemImageInfo +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Save System Image Info +ECHO %TIME:~0,8% Save System Image Info >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(c:\install\SetImageInfo.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/33-ChangeSomeAttributes/ChangeSomeAttributes.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/33-ChangeSomeAttributes/ChangeSomeAttributes.cmd new file mode 100644 index 0000000..3197a4c --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/33-ChangeSomeAttributes/ChangeSomeAttributes.cmd @@ -0,0 +1,142 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Change Some Attributes +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:ChangeSomeAttributes +TITLE ChangeSomeAttributes +SET Module=ChangeSomeAttributes +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\scripts >>%logfile_setup% +ATTRIB +A -R -S -H c:\scripts >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\scripts\PowerShell >>%logfile_setup% +ATTRIB +A -R -S -H c:\scripts\PowerShell >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\scripts\Batch >>%logfile_setup% +ATTRIB +A -R -S -H c:\scripts\Batch >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\Install /S /D >>%logfile_setup% +ATTRIB +A -R -S -H c:\Install /S /D >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\Temp /S /D >>%logfile_setup% +ATTRIB +A -R -S -H c:\Temp /S /D >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\scripts\powershell\*.* /S /D >>%logfile_setup% +ATTRIB +A -R -S -H c:\scripts\powershell\*.* /S /D >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\scripts\Batch\*.* /S /D >>%logfile_setup% +ATTRIB +A -R -S -H c:\scripts\Batch\*.* /S /D >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\tools\*.* /S /D >>%logfile_setup% +ATTRIB +A -R -S -H c:\tools\*.* /S /D >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\Install\*.* /S /D >>%logfile_setup% +ATTRIB +A -R -S -H c:\Install\*.* /S /D >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO %TIME:~0,8% ATTRIB +A -R -S -H c:\Temp\*.* /S /D >>%logfile_setup% +ATTRIB +A -R -S -H c:\Temp\*.* /S /D >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/34-BootstrapTheAllUserProfile/BootstrapTheAllUserProfile.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/34-BootstrapTheAllUserProfile/BootstrapTheAllUserProfile.cmd new file mode 100644 index 0000000..e287079 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/34-BootstrapTheAllUserProfile/BootstrapTheAllUserProfile.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Bootstrap The All User Profile +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:BootstrapTheAllUserProfile +TITLE BootstrapTheAllUserProfile +SET Module=BootstrapTheAllUserProfile +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Bootstrap the All User Profile +ECHO %TIME:~0,8% Bootstrap the All User Profile >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Invoke-BootstrapAllUserProfile.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/35-UpdateAllMicrosoftStoreApps/UpdateAllMicrosoftStoreApps.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/35-UpdateAllMicrosoftStoreApps/UpdateAllMicrosoftStoreApps.cmd new file mode 100644 index 0000000..4048ac6 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/35-UpdateAllMicrosoftStoreApps/UpdateAllMicrosoftStoreApps.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Update All Microsoft Store Apps +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:UpdateAllMicrosoftStoreApps +TITLE UpdateAllMicrosoftStoreApps +SET Module=UpdateAllMicrosoftStoreApps +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Update all Microsoft Store Apps +ECHO %TIME:~0,8% Update all Microsoft Store Apps >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Update-AllMicrosoftStoreApps.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/36-InstallTheMicrosoftOfficeSuite/InstallTheMicrosoftOfficeSuite.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/36-InstallTheMicrosoftOfficeSuite/InstallTheMicrosoftOfficeSuite.cmd new file mode 100644 index 0000000..f14cd3f --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/36-InstallTheMicrosoftOfficeSuite/InstallTheMicrosoftOfficeSuite.cmd @@ -0,0 +1,97 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Install The Microsoft Office Suite +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:InstallTheMicrosoftOfficeSuite +TITLE InstallTheMicrosoftOfficeSuite +SET Module=InstallTheMicrosoftOfficeSuite +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +PUSHD c:\install\Office\ >nul 2>&1 + +ECHO Install our default office deployment +ECHO %TIME:~0,8% Install our default office deployment >>%logfile_setup% 2>&1 +start /MIN /WAIT "Install our default office deployment" C:\install\Office\setup.exe /configure c:\install\Office\Configuration.xml >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +POPD >nul 2>&1 + +ECHO Clean up after the office setup is done +ECHO %TIME:~0,8% Clean up after the office setup is done >>%logfile_setup% 2>&1 +if exist c:\install\Office\ rd /s /q c:\install\Office\ >>%logfile_setup% 2>&1 + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/37-InstallSomePowerShellModules/InstallSomePowerShellModules.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/37-InstallSomePowerShellModules/InstallSomePowerShellModules.cmd new file mode 100644 index 0000000..deed987 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/37-InstallSomePowerShellModules/InstallSomePowerShellModules.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Install Some PowerShell Modules +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:InstallSomePowerShellModules +TITLE InstallSomePowerShellModules +SET Module=InstallSomePowerShellModules +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Install some PowerShell Modules +ECHO %TIME:~0,8% Install some PowerShell Modules >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Install-PowerShellModules_required.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/38-UpdateHelpFilesForAllInstalledPowerShellModules/UpdateHelpFilesForAllInstalledPowerShellModules.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/38-UpdateHelpFilesForAllInstalledPowerShellModules/UpdateHelpFilesForAllInstalledPowerShellModules.cmd new file mode 100644 index 0000000..99e07a3 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/38-UpdateHelpFilesForAllInstalledPowerShellModules/UpdateHelpFilesForAllInstalledPowerShellModules.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Update Help Files For All Installed PowerShell Modules +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:UpdateHelpFilesForAllInstalledPowerShellModules +TITLE UpdateHelpFilesForAllInstalledPowerShellModules +SET Module=UpdateHelpFilesForAllInstalledPowerShellModules +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Update help files for all installed PowerShell Modules +ECHO %TIME:~0,8% Update help files for all installed PowerShell Modules >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Update-PowerShellModulesHelp.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/39-InstallSomeVCRedistributableChocoPackages/InstallSomeVCRedistributableChocoPackages.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/39-InstallSomeVCRedistributableChocoPackages/InstallSomeVCRedistributableChocoPackages.cmd new file mode 100644 index 0000000..8e6c922 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/39-InstallSomeVCRedistributableChocoPackages/InstallSomeVCRedistributableChocoPackages.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Install Some VC Redistributable Choco Packages +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:InstallSomeVCRedistributableChocoPackages +TITLE InstallSomeVCRedistributableChocoPackages +SET Module=InstallSomeVCRedistributableChocoPackages +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Install some VC Redistributable Choco packages +ECHO %TIME:~0,8% Install some VC Redistributable Choco packages >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(c:\scripts\PowerShell\Install-ChocoPackages_vcredist.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/40-InstallDefaultDotNETChocoPackages/InstallDefaultDotNETChocoPackages.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/40-InstallDefaultDotNETChocoPackages/InstallDefaultDotNETChocoPackages.cmd new file mode 100644 index 0000000..70aa381 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/40-InstallDefaultDotNETChocoPackages/InstallDefaultDotNETChocoPackages.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Install Default .NET Choco Packages +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:InstallDefaultDotNETChocoPackages +TITLE InstallDefaultDotNETChocoPackages +SET Module=InstallDefaultDotNETChocoPackages +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Install default .NET Choco packages +ECHO %TIME:~0,8% Install default .NET Choco packages >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(c:\scripts\PowerShell\Install-ChocoPackages_dotnet.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/41-InstallChocoDefaultPackages/InstallChocoDefaultPackages.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/41-InstallChocoDefaultPackages/InstallChocoDefaultPackages.cmd new file mode 100644 index 0000000..c5ede1e --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/41-InstallChocoDefaultPackages/InstallChocoDefaultPackages.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment (ETPOSD) +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Install Choco Default Packages +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:InstallChocoDefaultPackages +TITLE InstallChocoDefaultPackages +SET Module=InstallChocoDefaultPackages +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Install Choco default packages +ECHO %TIME:~0,8% Install Choco default packages >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(c:\scripts\PowerShell\Install-ChocoPackages.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/50-ManufacturerSpecificConfigAndSoftwareInstallation/ManufacturerSpecificConfigAndSoftwareInstallation.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/50-ManufacturerSpecificConfigAndSoftwareInstallation/ManufacturerSpecificConfigAndSoftwareInstallation.cmd new file mode 100644 index 0000000..0fc4b09 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/50-ManufacturerSpecificConfigAndSoftwareInstallation/ManufacturerSpecificConfigAndSoftwareInstallation.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Manufacturer Specific Config And Software Installation +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:ManufacturerSpecificConfigAndSoftwareInstallation +TITLE ManufacturerSpecificConfigAndSoftwareInstallation +SET Module=ManufacturerSpecificConfigAndSoftwareInstallation +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Manufacturer specific config and software installation +ECHO %TIME:~0,8% Manufacturer specific config and software installation >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\install\ManufacturerSpecific.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/70-KmsHandling/KmsHandling.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/70-KmsHandling/KmsHandling.cmd new file mode 100644 index 0000000..4931b87 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/70-KmsHandling/KmsHandling.cmd @@ -0,0 +1,155 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: KMS Activation and Handling +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:KmsHandling +TITLE KmsHandling +SET Module=KmsHandling +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Turn on Windows Script Host +ECHO %TIME:~0,8% Turn on Windows Script Host >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (New-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows Script Host\Settings' -Name Enabled -PropertyType DWord -Value 1 -Force -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:ApplyMicrosoftWindows10EnterpriseKey +:: https://docs.microsoft.com/de-de/windows-server/get-started/kmsclientkeys +ECHO Apply Microsoft Windows 10 Enterprise key +ECHO %TIME:~0,8% Apply Microsoft Windows 10 Enterprise key >>%logfile_setup% +"%SystemRoot%\System32\cscript.exe" //nologo c:\windows\system32\slmgr.vbs /ipk NPPR9-FWDCX-D2C8J-H872K-2YT43 >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:SetTheInternalKMSServerForWindows10 +:: For now, this will need VPN +ECHO Set the internal KMS Server for Windows 10 +ECHO %TIME:~0,8% Set the internal KMS Server for Windows 10 >>%logfile_setup% +"%SystemRoot%\System32\cscript.exe" //nologo c:\windows\system32\slmgr.vbs /skms kms.enatec.net >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: Ping the KMS server for Windows 10 activation +:CheckW10KMSViaPing +ping -n 3 -w 1000 kms.enatec.net >null 2>&1 +if %errorlevel% GTR 0 goto ChangeToTheOfficeDirectory + +:ActivateWindows10ViaInternalKMSServer +:: For now, this will need VPN +ECHO Activate Windows 10 via internal KMS Server +ECHO %TIME:~0,8% Activate Windows 10 via internal KMS Server >>%logfile_setup% +"%SystemRoot%\System32\cscript.exe" //nologo c:\windows\system32\slmgr.vbs /ato >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:ChangeToTheOfficeDirectory +ECHO Change to the Office directory +ECHO %TIME:~0,8% Change to the Office directory >>%logfile_setup% +PUSHD "%ProgramFiles%\Microsoft Office\Office16" >nul 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:ApplyMicrosoftOfficeProfessionalPlus2019Key +ECHO Apply Microsoft Office Professional Plus 2019 key +ECHO %TIME:~0,8% Apply Microsoft Office Professional Plus 2019 key >>%logfile_setup% +"%SystemRoot%\System32\cscript.exe" //nologo ospp.vbs /inpkey:NMMKJ-6RK4F-KMJVX-8D9MJ-6MWKP >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: Ping the KMS server for Office activation +:CheckOfficeKMSViaPing +ping -n 3 -w 1000 kms.enatec.net >null 2>&1 +if %errorlevel% GTR 0 goto endInternalKMSServer + +:SetTheInternalKMSServerForOfficeProducts +ECHO Set the internal KMS Server for Office products +ECHO %TIME:~0,8% Set the internal KMS Server for Office products >>%logfile_setup% +"%SystemRoot%\System32\cscript.exe" //nologo ospp.vbs /sethst:kms.enatec.net >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: For now, this will need VPN +:ActivateTheOffice2019ProductsViaTheInternalKMSServer +ECHO Activate Office Professional Plus 2019 via internal KMS Server +ECHO %TIME:~0,8% Activate Office Professional Plus 2019 via internal KMS Server >>%logfile_setup% +"%SystemRoot%\System32\cscript.exe" //nologo ospp.vbs /act >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:endInternalKMSServer +POPD >nul 2>&1 + +:DisableWindowsScriptHost +:: Turn off Windows Script Host (current user only) +ECHO Turn off Windows Script Host +ECHO %TIME:~0,8% Turn on Windows Script Host >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (New-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows Script Host\Settings' -Name Enabled -PropertyType DWord -Value 0 -Force -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/71-WinRMTwaeks/WinRMTwaeks.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/71-WinRMTwaeks/WinRMTwaeks.cmd new file mode 100644 index 0000000..400f91d --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/71-WinRMTwaeks/WinRMTwaeks.cmd @@ -0,0 +1,182 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Change Handling and tweaks Windows Remote Management (WinRM) - PLEASE READ THE NOTE BELOW +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: PLEASE NOTE THIS: This can become a security issue! <- <- <- +:: +:: This script makes Windows Remote Management (WinRM) insecure!!! +:: We do this by purpose, we will reconfigure it later with an Intune Poliy. +:: We use it to administer the system within the local network, and this makes +:: it much easier to use Mac's or Linux systems to connect to this system. +:: +:: It will be skipped if outside of the enabling Technology network (or use VPN). +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:WinRMTwaeks +TITLE WinRMTwaeks +SET Module=WinRMTwaeks +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +: Use GHOST to figure out, if this system is connected directly to our Intranet +ping -n 3 -w 1000 ghost.enatec.net >null 2>&1 +if %errorlevel% GTR 0 goto NotConnected + +:EnableWindowsScriptHost +ECHO Turn on Windows Script Host +ECHO %TIME:~0,8% Turn on Windows Script Host >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (New-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows Script Host\Settings' -Name Enabled -PropertyType DWord -Value 1 -Force -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +: Enable Remote PowerShell +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "Enable-PSRemoting -Force -ErrorAction Continue" + +: Quick default configuration for Windows Remote Management (WinRM) +C:\Windows\system32\winrm.cmd quickconfig -q >null 2>&1 + +: Specifies the transport to use to send and receive WS-Management +: protocol requests and responses. +: The value must be either HTTP or HTTPS +C:\Windows\system32\winrm.cmd quickconfig -transport:http >null 2>&1 + +: Specifies the maximum time-out, in milliseconds, +: that can be used for any request other than Pull requests +: The default is 60000 +C:\Windows\system32\winrm.cmd set winrm/config '@{MaxTimeoutms="1800000"}' >null 2>&1 + +: Specifies the maximum amount of memory allocated per shell, +: including the shell's child processes. +: The default is 150 MB +C:\Windows\system32\winrm.cmd set winrm/config/winrs '@{MaxMemoryPerShellMB="800"}' >null 2>&1 + +: Allows the client computer to request unencrypted traffic. +: By default, the client computer requires encrypted network traffic +: and this setting is False. +C:\Windows\system32\winrm.cmd set winrm/config/service '@{AllowUnencrypted="true"}' >null 2>&1 + +: Allows the client computer to use Basic authentication. +: Basic authentication is a scheme in which the user name and password +: are sent in clear text to the server or proxy. +: This method is the least secure method of authentication. +: The default is True. +C:\Windows\system32\winrm.cmd set winrm/config/service/auth '@{Basic="true"}' >null 2>&1 + +: Allows the client computer to use Basic authentication. +: Basic authentication is a scheme in which the user name and password +: are sent in clear text to the server or proxy. +: This method is the least secure method of authentication. +: The default is True. +C:\Windows\system32\winrm.cmd set winrm/config/client/auth '@{Basic="true"}' >null 2>&1 + +: Allows the client to use Credential Security Support Provider (CredSSP) authentication. +: CredSSP enables an application to delegate the user's credentials +: from the client computer to the target server. +: The default is False. +C:\Windows\system32\winrm.cmd set winrm/config/service/auth '@{CredSSP="true"}' >null 2>&1 + +: Specifies the TCP port for which this listener is created. +: WinRM 2.0: The default HTTP port is 5985. +C:\Windows\system32\winrm.cmd set winrm/config/listener?Address=*+Transport=HTTP '@{Port="5985"}' >null 2>&1 + +: Allow the Windows Remote Administration Rule Group +C:\Windows\system32\netsh.exe advfirewall firewall set rule group="Windows Remote Administration" new enable=yes >null 2>&1 + +: Allow the Windows Remote Management (HTTP-In) Rule +C:\Windows\system32\netsh.exe advfirewall firewall set rule name="Windows Remote Management (HTTP-In)" new localport=5985 enable=yes action=allow >null 2>&1 + +: Allow the Windows Remote Management (HTTPS-In) Rule +C:\Windows\system32\netsh.exe advfirewall firewall set rule name="Windows Remote Management (HTTPS-In)" new localport=5986 enable=yes action=allow >null 2>&1 + +: Enable the Autostart of the Windows Remote Management (WinRM) Windows Service +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "Set-Service winrm -startuptype 'auto'" >null 2>&1 + +: Restart the Windows Remote Management (WinRM) Service +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "Restart-Service winrm" >null 2>&1 + +:DisableWindowsScriptHost +:: Turn off Windows Script Host (current user only) +ECHO Turn off Windows Script Host +ECHO %TIME:~0,8% Turn on Windows Script Host >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (New-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows Script Host\Settings' -Name Enabled -PropertyType DWord -Value 0 -Force -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul +goto ENDLOGIC + +:NotConnected +ECHO This Host is not connected directly to the Intranet (Skipped) +ECHO %TIME:~0,8% This Host is not connected directly to the Intranet (Skipped) >>%logfile_setup% +goto ENDLOGIC + +:ENDLOGIC +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/97-DesktopCleanup/DesktopCleanup.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/97-DesktopCleanup/DesktopCleanup.cmd new file mode 100644 index 0000000..fee1d2d --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/97-DesktopCleanup/DesktopCleanup.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Desktop Cleanup +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:DesktopCleanup +TITLE DesktopCleanup +SET Module=DesktopCleanup +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Desktop Cleanup +ECHO %TIME:~0,8% Desktop Cleanup >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Remove-AllPublicDesktopLinks.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/98-SetPowerPlanToAuto/SetPowerPlanToAuto.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/98-SetPowerPlanToAuto/SetPowerPlanToAuto.cmd new file mode 100644 index 0000000..b408012 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/98-SetPowerPlanToAuto/SetPowerPlanToAuto.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Set Power Plan To Auto +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:SetPowerPlanToAuto +TITLE SetPowerPlanToAuto +SET Module=SetPowerPlanToAuto +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Set Power Plan to Auto +ECHO %TIME:~0,8% Set Power Plan to Auto >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "c:\scripts\PowerShell\Set-PowerPlanToAuto.ps1" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/99-SetDefaultStartMenu/SetDefaultStartMenu.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/99-SetDefaultStartMenu/SetDefaultStartMenu.cmd new file mode 100644 index 0000000..59603f2 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/99-SetDefaultStartMenu/SetDefaultStartMenu.cmd @@ -0,0 +1,89 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Set Default Start Menu +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:SetDefaultStartMenu +TITLE SetDefaultStartMenu +SET Module=SetDefaultStartMenu +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +ECHO Set the default Start menu +ECHO %TIME:~0,8% Set the default Start menu >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Set-DefaultStartMenu.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/BootOOBE.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/BootOOBE.ps1 new file mode 100644 index 0000000..ab27fee --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/BootOOBE.ps1 @@ -0,0 +1,84 @@ +#requires -Version 3.0 + +<# + .SYNOPSIS + Interrupt the OOBE Process and starts our own + + .DESCRIPTION + Interrupt the OOBE Process and starts our own + + .EXAMPLE + PS C:\> .\BootOOBE.ps1 + + .NOTES + Adopted from Roger Zander (@rzander) + + .LINK + https://github.com/rzander/mOSD +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + $SCT = 'SilentlyContinue' + + $PantherUA = "$env:windir\Panther\unattend.xml" + + #region + $paramGetProcess = @{ + Name = 'sysprep' + ErrorAction = $SCT + } + $paramStopProcess = @{ + Force = $true + ErrorAction = $SCT + } + #endregion +} + +process +{ + $paramSetLocation = @{ + Path = $PSScriptRoot + ErrorAction = $SCT + } + $null = (Set-Location @paramSetLocation) + + $null = (Get-Process @paramGetProcess | Stop-Process @paramStopProcess) + + #Cleanup + $paramTestPath = @{ + Path = $PantherUA + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $PantherUA + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $null = (Get-Process @paramGetProcess | Stop-Process @paramStopProcess) + + Start-Sleep -Seconds 2 + + # Start the sysprep process + try + { + $null = (Start-Process -FilePath "$env:windir\System32\Sysprep\sysprep.exe" -ArgumentList '/oobe /quiet /reboot /unattend:C:\Windows\system32\sysprep\unattend.xml' -Wait) + } + catch + { + exit (1) + } +} + +end +{ + exit (0) +} diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/SetupComplete.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/SetupComplete.cmd new file mode 100644 index 0000000..41b5eef --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/SetupComplete.cmd @@ -0,0 +1,102 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Setup Complete Wrapper +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:SetupComplete +TITLE SetupComplete +SET Module=SetupComplete +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:LOGIC +: Change some attributes of the Scripts directory +attrib +A -R -S -H %windir%\setup\SCRIPTS\*.* /S /D + +: Start any existing CMD file (including subfolders) +CD %systemroot%\setup\SCRIPTS +FOR /D %%f in (*) do ( + PUSHD %%f + FOR %%g in (*.cmd) do ( + ECHO Call %%g >>%logfile_setup% 2>nul + call %%g >nul 2>&1 + : START /MIN /WAIT "%%g" %%g + ECHO.>>%logfile_setup% 2>nul + ) + POPD +) + +ECHO.>>%logfile_setup% 2>nul + +ECHO Finished %Module% on %DATE:~0% - %TIME:~0,8% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + +: Clean up after the setup is done +IF EXIST %systemroot%\setup\SCRIPTS\done RD /s /q %systemroot%\setup\SCRIPTS >nul 2>&1 + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2021, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/done b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Setup/Scripts/done new file mode 100644 index 0000000..e69de29 diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/System32/oemlogo.bmp b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/System32/oemlogo.bmp new file mode 100644 index 0000000..f44ded0 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/System32/oemlogo.bmp differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/System32/sysprep/unattend.xml b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/System32/sysprep/unattend.xml new file mode 100644 index 0000000..b3d13d8 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/System32/sysprep/unattend.xml @@ -0,0 +1,33 @@ + + + + + 047:00000407 + en-US + de-DE + + + + 3 + true + true + Work + + + + + + + OOBE + + + + + diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1024x768.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1024x768.jpg new file mode 100644 index 0000000..69e93da Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1024x768.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1200x1920.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1200x1920.jpg new file mode 100644 index 0000000..055ceb7 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1200x1920.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1366x768.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1366x768.jpg new file mode 100644 index 0000000..ea6f332 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1366x768.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1600x2560.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1600x2560.jpg new file mode 100644 index 0000000..b578b62 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_1600x2560.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_2160x3840.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_2160x3840.jpg new file mode 100644 index 0000000..fb2332c Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_2160x3840.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_2560x1600.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_2560x1600.jpg new file mode 100644 index 0000000..e247cd1 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_2560x1600.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_3840x2160.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_3840x2160.jpg new file mode 100644 index 0000000..c225318 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_3840x2160.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_768x1024.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_768x1024.jpg new file mode 100644 index 0000000..0312796 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_768x1024.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_768x1366.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_768x1366.jpg new file mode 100644 index 0000000..478b2e1 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/4K/Wallpaper/Windows/img0_768x1366.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img100.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img100.jpg new file mode 100644 index 0000000..558b692 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img100.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img101.png b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img101.png new file mode 100644 index 0000000..adc9e78 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img101.png differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img102.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img102.jpg new file mode 100644 index 0000000..b37b63b Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img102.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img103.png b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img103.png new file mode 100644 index 0000000..27a2e46 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img103.png differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img104.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img104.jpg new file mode 100644 index 0000000..f9d8c9b Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img104.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img105.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img105.jpg new file mode 100644 index 0000000..5dbe9c3 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Screen/img105.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img1.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img1.jpg new file mode 100644 index 0000000..bc1e5ac Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img1.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img13.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img13.jpg new file mode 100644 index 0000000..a6ebdb1 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img13.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img2.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img2.jpg new file mode 100644 index 0000000..1d8fa95 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img2.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img3.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img3.jpg new file mode 100644 index 0000000..2e02df5 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img3.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img4.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img4.jpg new file mode 100644 index 0000000..430b558 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme1/img4.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img10.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img10.jpg new file mode 100644 index 0000000..a3a6810 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img10.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img11.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img11.jpg new file mode 100644 index 0000000..9fdb100 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img11.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img12.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img12.jpg new file mode 100644 index 0000000..9dea7f3 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img12.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img7.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img7.jpg new file mode 100644 index 0000000..8e753f6 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img7.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img8.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img8.jpg new file mode 100644 index 0000000..0dd2286 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img8.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img9.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img9.jpg new file mode 100644 index 0000000..f4d4038 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Theme2/img9.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/WIP-6th-anniversary-wallpaper-dark.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/WIP-6th-anniversary-wallpaper-dark.jpg new file mode 100644 index 0000000..5abfd00 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/WIP-6th-anniversary-wallpaper-dark.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/WIP-6th-anniversary-wallpaper-light.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/WIP-6th-anniversary-wallpaper-light.jpg new file mode 100644 index 0000000..761c60f Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/WIP-6th-anniversary-wallpaper-light.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/img0.jpg b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/img0.jpg new file mode 100644 index 0000000..e5fd6b5 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/Web/Wallpaper/Windows/img0.jpg differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/provisioning/Autopilot/AutopilotConfigurationFile.json b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/provisioning/Autopilot/AutopilotConfigurationFile.json new file mode 100644 index 0000000..9d4f3e1 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$$/provisioning/Autopilot/AutopilotConfigurationFile.json @@ -0,0 +1,16 @@ +{ + "CloudAssignedDomainJoinMethod": 0, + "CloudAssignedDeviceName": "ENATEC-%SERIAL%", + "CloudAssignedAutopilotUpdateTimeout": 1800000, + "CloudAssignedForcedEnrollment": 1, + "Version": 2049, + "CloudAssignedTenantId": "b768b3c4-dc4b-445c-94c0-388882f966fb", + "CloudAssignedAutopilotUpdateDisabled": 1, + "ZtdCorrelationId": "ae8249a2-ad5d-426a-99a0-2aba35426014", + "Comment_File": "Profile DEFAULT", + "CloudAssignedAadServerData": "{\"ZeroTouchConfig\":{\"CloudAssignedTenantUpn\":\"\",\"ForcedEnrollment\":1,\"CloudAssignedTenantDomain\":\"hochwald.net\"}}", + "CloudAssignedOobeConfig": 1308, + "CloudAssignedLockdownConfig": 1, + "CloudAssignedTenantDomain": "hochwald.net", + "CloudAssignedLanguage": "en-US" +} diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific.ps1 new file mode 100644 index 0000000..1a9033c --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific.ps1 @@ -0,0 +1,520 @@ +#requires -Version 5.0 -Modules BitsTransfer, CimCmdlets -RunAsAdministrator + +<# + .SYNOPSIS + Install manufacturer/vendor specific software + + .DESCRIPTION + Install manufacturer/vendor specific software + For now, just HP is supported. + + .NOTES + The OEM Info is no longer displayed in newer Builds of Windows 10! + Starting with Windows 10 Build 20H2 the Logo and other OEM Info is no longer displayed. + Focus will be the installation of Tools to support the vendor specific drivers and tooling + + Request: + If you are interessted in Dell or Lenovo support, please open a issue/ticket. + We look for pilot/beta users, due to missing hardware the development is a bit hard. + + Changelog: + 1.0.7: Download the latest HP versions and install it silently + 1.0.6: Fallback to older HP Support Assistant version (Due to Silent Install Issues) + 1.0.5: Moved the installer path + 1.0.4: Rewrite big parts and create a cleanup helper + 1.0.3: Replace old WMI call with CIM - Fix Write-Output + 1.0.2: Update HP tooling (Files) + 1.0.1: Update Lenovo tooling (Files) + + Version 1.0.7 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Manufacturer specific config and software installation' + + #region Defaults + $SCT = 'SilentlyContinue' + $STP = 'Stop' + + # Splat the defaults + $paramSimpleDefaults = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + + # Change this, if needed + $Company = 'enabling Technology' + + # Do not change this! + $RegistryPath = ('HKLM:\Software\' + $Company + '\BaseImage') + + # Get the Info + $Manufacturer = (Get-ItemPropertyValue -Path $RegistryPath -Name HardwareManufacturer @paramSimpleDefaults) + + # Set the Path Info + $OemInfoPath = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation' + + # Read the Info from CIM + $ManufacturerModel = ((Get-CimInstance -ClassName Win32_Computersystem @paramSimpleDefaults) | Select-Object -ExpandProperty Model) + + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force @paramSimpleDefaults) + + + if (-not $ManufacturerModel) + { + $ManufacturerModel = 'Unknown' + } + + if ($Manufacturer) + { + switch ($Manufacturer) + { + 'HP' + { + $ManufacturerTooling = 'HP' + } + 'Hewlett-Packard' + { + $ManufacturerTooling = 'HP' + } + 'Dell' + { + $ManufacturerTooling = 'Dell' + Write-Warning -Message 'Dell support is in still in development' + } + 'LENOVO' + { + $ManufacturerTooling = 'LENOVO' + Write-Warning -Message 'Lenovo support is in still in development' + } + 'Microsoft Corporation' + { + $ManufacturerTooling = 'HYPERV' + Write-Warning -Message 'Microsoft Hyper-V is not (yet) supported, but planned' + Return + } + 'VMware, Inc.' + { + $ManufacturerTooling = 'VMware' + Write-Warning -Message 'VMware is not (yet) supported' + Return + } + 'Parallels Software International Inc.' + { + $ManufacturerTooling = 'Parallels' + Write-Warning -Message 'Parallels is not (yet) supported' + Return + } + Default + { + $ManufacturerTooling = $null + Write-Warning -Message 'Unknown and/or unsupported manufacturer' + Return + } + } + } + else + { + $ManufacturerTooling = $null + Write-Warning -Message 'Unknown and/or unsupported manufacturer' + Return + } + + # Splat the defaults for New-ItemProperty + $paramNewItemProperty = @{ + Path = $OemInfoPath + PropertyType = 'String' + Force = $true + Confirm = $false + WhatIf = $false + ErrorAction = $SCT + WarningAction = $SCT + } + + # Splat the defaults for Copy-Item + $paramCopyItem = @{ + Destination = "$env:windir\SYSTEM32\SYSTEM.BMP" + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + #endregion Defaults + + #region RemoveOEMInfo + function Remove-OEMInfo + { + <# + .SYNOPSIS + Cleanup the OEM Info + + .DESCRIPTION + Cleanup the OEM Info from the registry + + .PARAMETER Path + The Registry Path + + .EXAMPLE + PS C:\> Remove-OEMInfo + + .EXAMPLE + PS C:\> Remove-OEMInfo -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation' + + .NOTES + Internal Helper + #> + [CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [Alias('OemInfoPath')] + [string] + $Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\OEMInformation' + ) + + begin + { + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + $ValuesToClean = @( + 'Model' + 'Manufacturer' + 'Logo' + 'SupportAppURL' + 'SupportURL' + 'SupportHours' + 'SupportPhone' + ) + #endregion + } + + process + { + if ($pscmdlet.ShouldProcess('OEM Info', 'Delete')) + { + # Cleanup the OEM Info + foreach ($ValueToClean in $ValuesToClean) + { + $paramGetItemPropertyValue = @{ + Path = $Path + Name = $ValueToClean + ErrorAction = $SCT + WarningAction = $SCT + } + + if (Get-ItemPropertyValue @paramGetItemPropertyValue) + { + $paramRemoveItemProperty = @{ + Path = $Path + Name = $ValueToClean + Force = $true + WhatIf = $false + ErrorAction = $SCT + WarningAction = $SCT + Confirm = $false + } + $null = (Remove-ItemProperty @paramRemoveItemProperty) + } + + $ValueToClean = $null + } + } + } + } + #endregion RemoveOEMInfo +} + +process +{ + #region HP + if ($ManufacturerTooling -eq 'HP') + { + # Cleanup the OEM Info + $null = (Remove-OEMInfo @paramSimpleDefaults) + + # Copy the OEM Logo + if (Test-Path -Path "$env:HOMEDRIVE\install\ManufacturerSpecific\hp\SYSTEM.BMP" @paramSimpleDefaults) + { + $null = (Copy-Item -Path "$env:HOMEDRIVE\install\ManufacturerSpecific\hp\SYSTEM.BMP" @paramCopyItem) + } + + # Set the new OEM Info + if ($ManufacturerModel) + { + $null = (New-ItemProperty -Name 'Model' -Value $ManufacturerModel @paramNewItemProperty) + } + + $null = (New-ItemProperty -Name 'Manufacturer' -Value 'HP Inc.' @paramNewItemProperty) + $null = (New-ItemProperty -Name 'Logo' -Value 'C:\\WINDOWS\\SYSTEM32\\SYSTEM.BMP' @paramNewItemProperty) + $null = (New-ItemProperty -Name 'SupportAppURL' -Value 'hpsupportassistant://GetAssist?LaunchPoint=51' @paramNewItemProperty) + $null = (New-ItemProperty -Name 'SupportURL' -Value 'http://support.hp.com' @paramNewItemProperty) + + # Install the HP Tools + #region HPDefaults + $BitsTransferPolicy = 'Always' + $BitsTransferPriority = 'High' + $HPSilentSwitchesExtractDefault = '/s /e /f' + $HPSilentSwitchesDefault = '/s /a /s /v" /qn"' + $PowerShellExecutable = ($PSHome + '\powershell.exe') + $ErrorMessage = 'Installer not found!' + $DriverTempDir = "$env:HOMEDRIVE\install\temp" + #endregion HPDefaults + + #region sp108770 + $paramTestPath = @{ + Path = $DriverTempDir + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $DriverTempDir + ItemType = 'Directory' + Force = $true + Confirm = $false + } + $null = (New-Item @paramNewItem) + } + + $RequestContent = 'https://ftp.hp.com/pub/softpaq/sp108501-109000/sp108770.exe' + + $DriverExtractDest = "$env:HOMEDRIVE\install\sp108770" + + $paramTestPath = @{ + Path = $DriverExtractDest + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $DriverExtractDest + ItemType = 'Directory' + Force = $true + Confirm = $false + } + $null = (New-Item @paramNewItem) + } + + [string]$Installer = ($DriverTempDir + '\sp108770.exe') + + $paramTestPath = @{ + Path = $Installer + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + # Use BitsTransfer to download the latest installer + $paramStartBitsTransfer = @{ + Source = $RequestContent + Destination = $Installer + Priority = $BitsTransferPriority + TransferPolicy = $BitsTransferPolicy + ErrorAction = $STP + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + } + + $HPSilentSwitchesExtract = ($HPSilentSwitchesExtractDefault + ' "' + $DriverExtractDest + '"') + $paramStartProcess = @{ + FilePath = $PowerShellExecutable + WorkingDirectory = $DriverExtractDest + ArgumentList = ($Installer + ' ' + $HPSilentSwitchesExtract) + NoNewWindow = $true + Wait = $true + } + $null = (Start-Process @paramStartProcess) + + $HPInstaller = ($DriverExtractDest + '\InstallHPSA.exe') + + $paramTestPath = @{ + Path = $HPInstaller + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $HPSilentSwitches = $HPSilentSwitchesDefault + $paramStartProcess = @{ + FilePath = $PowerShellExecutable + WorkingDirectory = $DriverExtractDest + ArgumentList = ($HPInstaller + ' ' + $HPSilentSwitches) + NoNewWindow = $true + Wait = $true + } + $null = (Start-Process @paramStartProcess) + } + else + { + Write-Warning -Message $ErrorMessage + } + #endregion sp108770 + + #region sp107493 + $RequestContent = 'https://ftp.hp.com/pub/softpaq/sp107001-107500/sp107493.exe' + + $DriverExtractDest = "$env:HOMEDRIVE\install\sp107493" + + $paramTestPath = @{ + Path = $DriverExtractDest + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $DriverExtractDest + ItemType = 'Directory' + Force = $true + Confirm = $false + } + $null = (New-Item @paramNewItem) + } + + [string]$Installer = ($DriverTempDir + '\sp107493.exe') + + $paramTestPath = @{ + Path = $Installer + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + # Use BitsTransfer to download the latest installer + $paramStartBitsTransfer = @{ + Source = $RequestContent + Destination = $Installer + Priority = $BitsTransferPriority + TransferPolicy = $BitsTransferPolicy + ErrorAction = $STP + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + } + + $HPSilentSwitchesExtract = ($HPSilentSwitchesExtractDefault + ' "' + $DriverExtractDest + '"') + $paramStartProcess = @{ + FilePath = $PowerShellExecutable + WorkingDirectory = $DriverExtractDest + ArgumentList = ($Installer + ' ' + $HPSilentSwitchesExtract) + NoNewWindow = $true + Wait = $true + } + $null = (Start-Process @paramStartProcess) + + $HPInstaller = ($DriverExtractDest + '\InstallCmdWrapper.exe') + + $paramTestPath = @{ + Path = $HPInstaller + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $HPSilentSwitches = $HPSilentSwitchesDefault + $paramStartProcess = @{ + FilePath = $PowerShellExecutable + WorkingDirectory = $DriverExtractDest + ArgumentList = ($HPInstaller + ' ' + $HPSilentSwitches) + NoNewWindow = $true + Wait = $true + } + $null = (Start-Process @paramStartProcess) + } + else + { + Write-Warning -Message $ErrorMessage + } + #endregion sp107493 + } + #endregion HP + + #region LENOVO + if ($ManufacturerTooling -eq 'LENOVO') + { + # Cleanup the OEM Info + $null = (Remove-OEMInfo @paramSimpleDefaults) + + # Copy the OEM Logo + if (Test-Path -Path 'Lenovo\SYSTEM.BMP' @paramSimpleDefaults) + { + $null = (Copy-Item -Path "$env:HOMEDRIVE\install\ManufacturerSpecific\Lenovo\SYSTEM.BMP" @paramCopyItem) + } + + # Set the new OEM Info + if ($ManufacturerModel) + { + $null = (New-ItemProperty -Name 'Model' -Value $ManufacturerModel @paramNewItemProperty) + } + + $null = (New-ItemProperty -Name 'Manufacturer' -Value 'Lenovo' @paramNewItemProperty) + $null = (New-ItemProperty -Name 'Logo' -Value 'C:\\WINDOWS\\SYSTEM32\\SYSTEM.BMP' @paramNewItemProperty) + $null = (New-ItemProperty -Name 'SupportURL' -Value 'https://support.lenovo.com/' @paramNewItemProperty) + } + #endregion LENOVO + + #region Dell + if ($ManufacturerTooling -eq 'Dell') + { + # Cleanup the OEM Info + $null = (Remove-OEMInfo @paramSimpleDefaults) + + # Copy the OEM Logo + if (Test-Path -Path "$env:HOMEDRIVE\install\ManufacturerSpecific\Dell\SYSTEM.BMP" @paramSimpleDefaults) + { + $null = (Copy-Item -Path "$env:HOMEDRIVE\install\ManufacturerSpecific\Dell\SYSTEM.BMP" @paramCopyItem) + } + + # Set the new OEM Info + if ($ManufacturerModel) + { + $null = (New-ItemProperty -Name 'Model' -Value $ManufacturerModel @paramNewItemProperty) + } + + $null = (New-ItemProperty -Name 'Manufacturer' -Value 'Dell' @paramNewItemProperty) + $null = (New-ItemProperty -Name 'Logo' -Value 'C:\\WINDOWS\\SYSTEM32\\SYSTEM.BMP' @paramNewItemProperty) + $null = (New-ItemProperty -Name 'SupportURL' -Value 'https://www.dell.com/support/home/' @paramNewItemProperty) + } + #endregion Dell +} + +end +{ + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force @paramSimpleDefaults) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Dell/SYSTEM.BMP b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Dell/SYSTEM.BMP new file mode 100644 index 0000000..2341ee3 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Dell/SYSTEM.BMP differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Lenovo/SYSTEM.BMP b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Lenovo/SYSTEM.BMP new file mode 100644 index 0000000..4ec94f5 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Lenovo/SYSTEM.BMP differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Lenovo/install.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Lenovo/install.cmd new file mode 100644 index 0000000..f775a9f --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/Lenovo/install.cmd @@ -0,0 +1,10 @@ +title LenovoSpecific +set Module=LenovoSpecific +echo start %Module% %time% =================== >>%logfile_setup% + +rem install Lenovo System Update for Windows +echo system_update_5.07.0106.exe /VERYSILENT /SUPPRESSMSGBOXES /LOG='c:\temp\LenovoSysupdate.log' /NOCANCEL /NORESTART /CLOSEAPPLICATIONS /NORESTARTAPPLICATIONS >>%logfile_setup% +@system_update_5.07.0106.exe /VERYSILENT /SUPPRESSMSGBOXES /LOG='c:\temp\LenovoSysupdate.log' /NOCANCEL /NORESTART /CLOSEAPPLICATIONS /NORESTARTAPPLICATIONS >>%logfile_setup% + +echo stop %Module% %time% =================== >>%logfile_setup% +echo.>>%logfile_setup% diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/hp/SYSTEM.BMP b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/hp/SYSTEM.BMP new file mode 100644 index 0000000..98cbb46 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/ManufacturerSpecific/hp/SYSTEM.BMP differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/Office/Configuration.xml b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/Office/Configuration.xml new file mode 100644 index 0000000..c6ebd71 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/Office/Configuration.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/Office/setup.exe b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/Office/setup.exe new file mode 100644 index 0000000..c59b643 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/Office/setup.exe differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/SetImageInfo.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/SetImageInfo.ps1 new file mode 100644 index 0000000..1beebc9 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/SetImageInfo.ps1 @@ -0,0 +1,671 @@ +#requires -Version 5.0 -Modules CimCmdlets -RunAsAdministrator + +<# + .SYNOPSIS + Set the Install Image in the Registry + + .DESCRIPTION + Set the Install Image in the Registry. + Save several infos to the registry, we use that with some tools later. + + .PARAMETER Company + Name of the Company, used to create a registry Tree + + .PARAMETER ImageName + Name of the Install Image + + .PARAMETER ImageDescription + Description of the Install Image + + .PARAMETER ImageVersion + Version of the Install Image. + String is used here! + + .NOTES + Changelog: + 2.0.0: Completly rewritten and renamed + 1.0.2: Add Image Name & Version + 1.0.1: Fixed the site issue (Termination Error) + 1.0.0: Initial public beta + + Version 2.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'None')] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('InstallCompany')] + [string] + $Company = 'enabling Technology', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('InstallImageName')] + [string] + $ImageName = 'ETPOSD', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('InstallImageDescription')] + [string] + $ImageDescription = 'enabling Technology progressive OS deployment', + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('InstallImageVersion')] + [string] + $ImageVersion = 'Test Build' +) + +begin +{ + Write-Output -InputObject 'Set the Install Image in the Registry' + + #region GlobalDefaults + $SCT = 'SilentlyContinue' + + $RegSz = 'String' + $DefaultInfo = 'Unknown' + + # Target Path + $RegistryPath = ('HKLM:\Software\' + $Company + '\BaseImage') + #endregion GlobalDefaults + + #region HelperFunctions + function Get-ComputerSplit + { + <# + .SYNOPSIS + Find the own name via DNS, use the Hostname as fallback + + .DESCRIPTION + Find the own name via DNS, use the Hostname as fallback + + .PARAMETER ComputerName + The Computer(s) to use + + .EXAMPLE + Get-ComputerSplit -ComputerName Value + Describe what this call does + + .NOTES + Stolen from PsSharedGoods (MIT Licensed) + + .LINK + https://github.com/EvotecIT/PSSharedGoods + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param( + [string[]] $ComputerName = $ComputerName + ) + + begin + { + # Just in case + if ($null -eq $ComputerName) + { + $ComputerName = ($Env:COMPUTERNAME) + } + } + + process + { + try + { + # Do we have a registered Hostname in DNS? + $LocalComputerDNSName = ([Net.Dns]::GetHostByName($Env:COMPUTERNAME).HostName) + } + catch + { + # Fallback + $LocalComputerDNSName = ($Env:COMPUTERNAME) + } + + # Cleanup + $ComputersLocal = $null + + [Array] $Computers = foreach ($_ in $ComputerName) + { + if ($_ -eq '' -or $null -eq $_) + { + $_ = ($Env:COMPUTERNAME) + } + + if ($_ -ne $Env:COMPUTERNAME -and $_ -ne $LocalComputerDNSName) + { + $_ + } + else + { + $ComputersLocal = ($_) + } + } + , @($ComputersLocal, $Computers) + } + } + + function Get-CimData + { + <# + .SYNOPSIS + Get CIM Data + + .DESCRIPTION + Get CIM Data + + .PARAMETER ComputerName + Parameter description + + .PARAMETER Protocol + 'Default', 'Dcom', 'Wsman', default is 'Default' + + .PARAMETER Class + CIM Class + + .PARAMETER Properties + CIM Property or Properties + + .EXAMPLE + Get-CimData -Class 'win32_bios' -ComputerName AD1,EVOWIN + + Get-CimData -Class 'win32_bios' + + # Get-CimClass to get all classes + + .NOTES + Stolen from PsSharedGoods (MIT Licensed) + + .LINK + https://github.com/EvotecIT/PSSharedGoods + #> + [CmdletBinding(ConfirmImpact = 'Low')] + param([string] $Class, + [string] $NameSpace = 'root\cimv2', + [string[]] $ComputerName = $Env:COMPUTERNAME, + [ValidateSet('Default', 'Dcom', 'Wsman')][string] $Protocol = 'Default', + [string] $Properties = '*') + + begin + { + $SCT = 'SilentlyContinue' + $ExcludeProperties = 'CimClass', 'CimInstanceProperties', 'CimSystemProperties', 'SystemCreationClassName', 'CreationClassName' + } + + process + { + [Array] $ComputersSplit = (Get-ComputerSplit -ComputerName $ComputerName) + $CimObject = @(# requires removal of this property for query + [string[]] $PropertiesOnly = $Properties | Where-Object -FilterScript { + $_ -ne 'PSComputerName' + } + + $Computers = $ComputersSplit[1] + + if ($Computers.Count -gt 0) + { + if ($Protocol -eq 'Default') + { + (Get-CimInstance -ClassName $Class -ComputerName $Computers -ErrorAction $SCT -Property $PropertiesOnly -Namespace $NameSpace | Select-Object -Property $Properties -ExcludeProperty $ExcludeProperties) + } + else + { + $Option = (New-CimSessionOption -Protocol) + $Session = (New-CimSession -ComputerName $Computers -SessionOption $Option -ErrorAction $SCT) + $Info = (Get-CimInstance -ClassName $Class -CimSession $Session -ErrorAction $SCT -Property $PropertiesOnly -Namespace $NameSpace | Select-Object -Property $Properties -ExcludeProperty $ExcludeProperties) + $null = (Remove-CimSession -CimSession $Session -ErrorAction $SCT) + + $Info + } + } + + $Computers = $ComputersSplit[0] + + if ($Computers.Count -gt 0) + { + $Info = (Get-CimInstance -ClassName $Class -ErrorAction $SCT -Property $PropertiesOnly -Namespace $NameSpace | Select-Object -Property $Properties -ExcludeProperty $ExcludeProperties) + $Info | Add-Member -Name 'PSComputerName' -Value $Computers -MemberType NoteProperty -Force + + $Info + } + ) + + $CimComputers = ($CimObject.PSComputerName | Sort-Object -Unique) + + foreach ($Computer in $ComputerName) + { + if ($CimComputers -notcontains $Computer) + { + Write-Warning -Message ('Get-CimData - No data for computer {0}. Most likely an error on receiving side.' -f $Computer) + } + } + } + + end + { + return $CimObject + } + } + #endregion HelperFunctions + + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Disabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) +} + +process +{ + # Create Path if needed + $paramTestPath = @{ + Path = $RegistryPath + WarningAction = $SCT + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $RegistryPath + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + # Set Date/Time + $InstallDate = (Get-Date -Format 'yyyy-MM-dd') + $InstallTime = (Get-Date -Format 'HH:mm') + + # Get system info + $paramGetCimData = @{ + Class = 'Win32_ComputerSystem' + WarningAction = $SCT + ErrorAction = $SCT + } + $HardwareInfo = (Get-CimData @paramGetCimData) + + # Windows Info + $paramGetCimInstance = @{ + ClassName = 'Win32_OperatingSystem' + Property = 'CSName', 'Caption', 'Version', 'OSArchitecture' + WarningAction = $SCT + ErrorAction = $SCT + } + $WindowsVersionInfo = (Get-CimInstance @paramGetCimInstance | Select-Object -Property CSName, Caption, Version, OSArchitecture) + + # Release ID (e.g. 1903) + $paramGetItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' + Name = 'ReleaseId' + WarningAction = $SCT + ErrorAction = $SCT + } + $WindowsReleaseId = ((Get-ItemProperty @paramGetItemProperty ).ReleaseId) + + # Network Info + $paramGetCimInstance = @{ + ClassName = 'Win32_NetworkAdapterConfiguration' + select = 'IPAddress' + WarningAction = $SCT + ErrorAction = $SCT + } + $WindowsNicInfo = (Get-CimInstance @paramGetCimInstance | Where-Object -FilterScript { + $_.IPAddress + } | Select-Object -ExpandProperty IPAddress | Where-Object -FilterScript { + $_ -notlike '*:*' + }) + + #region ImageName + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'ImageName' + PropertyType = $RegSz + Value = $ImageName + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion ImageName + + #region ImageDescription + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'ImageDescription' + PropertyType = $RegSz + Value = $ImageDescription + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion ImageDescription + + #region ImageVersion + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'ImageVersion' + PropertyType = $RegSz + Value = $ImageVersion + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion ImageVersion + + #region KMSAware + $paramTestConnection = @{ + ComputerName = 'kms.enatec.net' + Quiet = $true + WarningAction = $SCT + ErrorAction = $SCT + } + [bool]$KMSAwareValue = (Test-Connection @paramTestConnection) + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'KMSAware' + PropertyType = $RegSz + Value = $KMSAwareValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion KMSAware + + #region InstallDate + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallDate' + PropertyType = $RegSz + Value = $InstallDate + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallDate + + #region InstallTime + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallTime' + PropertyType = $RegSz + Value = $InstallTime + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallTime + + #region InstallHostname + if ((($HardwareInfo).Name)) + { + $InstallHostnameValue = (($HardwareInfo).Name) + } + else + { + $InstallHostnameValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallHostname' + PropertyType = $RegSz + Value = $InstallHostnameValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallHostname + + #region InstallIP + if ($WindowsNicInfo) + { + $InstallIPValue = $WindowsNicInfo + } + else + { + $InstallIPValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallIP' + PropertyType = $RegSz + Value = $InstallIPValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallIP + + #region InstallSite + if (Test-Connection -ComputerName echo.enatec.net -Quiet -WarningAction $SCT -ErrorAction $SCT) + { + $InstallSiteValue = 'FRA1' + } + elseif (Test-Connection -ComputerName friend.enatec.net -Quiet -WarningAction $SCT -ErrorAction $SCT) + { + $InstallSiteValue = 'FRA2' + } + elseif (Test-Connection -ComputerName join.enatec.net -Quiet -WarningAction $SCT -ErrorAction $SCT) + { + $InstallSiteValue = 'VPN' + } + else + { + $InstallSiteValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallSite' + PropertyType = $RegSz + Value = $InstallSiteValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallSite + + #region HardwareManufacturer + if ((($HardwareInfo).Manufacturer)) + { + $HardwareManufacturerValue = (($HardwareInfo).Manufacturer) + } + else + { + $HardwareManufacturerValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'HardwareManufacturer' + PropertyType = $RegSz + Value = $HardwareManufacturerValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion HardwareManufacturer + + #region HardwareModel + if ((($HardwareInfo).Model)) + { + $HardwareModelValue = (($HardwareInfo).Model) + } + else + { + $HardwareModelValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'HardwareModel' + PropertyType = $RegSz + Value = $HardwareModelValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion HardwareModel + + #region InstallOperationsystem + if ((($WindowsVersionInfo).Caption)) + { + $InstallOperationsystemValue = (($WindowsVersionInfo).Caption) + } + else + { + $InstallOperationsystemValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallOperationsystem' + PropertyType = $RegSz + Value = $InstallOperationsystemValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallOperationsystem + + #region InstallArchitecture + if ((($WindowsVersionInfo).OSArchitecture)) + { + $InstallArchitectureValue = (($WindowsVersionInfo).OSArchitecture) + } + else + { + $InstallArchitectureValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallArchitecture' + PropertyType = $RegSz + Value = $InstallArchitectureValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallArchitecture + + #region InstallReleaseId + if ($WindowsReleaseId) + { + $InstallReleaseIdValue = $WindowsReleaseId + } + else + { + $InstallReleaseIdValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallReleaseId' + PropertyType = $RegSz + Value = $InstallReleaseIdValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallReleaseId + + #region InstallVersion + if ((($WindowsVersionInfo).Version)) + { + $InstallVersionValue = (($WindowsVersionInfo).Version) + } + else + { + $InstallVersionValue = $DefaultInfo + } + + $paramNewItemProperty = @{ + Path = $RegistryPath + Name = 'InstallVersion' + PropertyType = $RegSz + Value = $InstallVersionValue + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion InstallVersion +} + +end +{ + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Enabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/SystemBootstrapper.cmd b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/SystemBootstrapper.cmd new file mode 100644 index 0000000..55a5dc9 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Install/SystemBootstrapper.cmd @@ -0,0 +1,415 @@ +@ECHO OFF + +:: ******************************************************************************************************************** +:: +:: enabling Technology progressive OS deployment +:: Client System Bootstrapper for Windows 10 Enterprise Installations +:: +:: Version 1.0.0 +:: +:: Tested with Windows 10 Enterprise Release 2004 and Release 2009 +:: +:: Please review all the scripts BEFORE you install it on any of your systems. +:: This installation/configuration is customized to our internal requirements and might not fit for everyone! +:: +:: ******************************************************************************************************************** + +SETLOCAL + +:: check if runs as Administrator +OPENFILES >nul 2>&1 +IF %errorlevel%==0 ( + GOTO MakeNonCancelable +) ELSE ( + ECHO You are not running as Administrator... + ECHO This batch cannot do it's job without elevation! + ECHO. + ECHO Right-click and select ^'Run as Administrator^' and try again... + ECHO. + ECHO Press any key to exit... + PAUSE >nul + + EXIT +) + +:MakeNonCancelable +:: prevent CTRL + C +IF "%~1" EQU "NonCancelable" GOTO NonCancelable +START "" /B CMD /C "%~F0" NonCancelable +EXIT + +:NonCancelable +TITLE enabling Technology Client System Bootstrapper +SET Module=SystemBootstrapper +SET logfile_setup=%HOMEDRIVE%\Temp\%Module%.txt + +:: Show Splash Screen +START /LOW /MAX "Installation is running, please wait" c:\tools\enaTec_Installer.exe >nul 2>&1 + +:: Ensure NTP is used and that the time is correct +%SystemRoot%\System32\net.exe stop w32time >nul 2>&1 +%SystemRoot%\System32\w32tm.exe /config /syncfromflags:manual /manualpeerlist:"0.de.pool.ntp.org 1.de.pool.ntp.org 2.de.pool.ntp.org 3.de.pool.ntp.org" >nul 2>&1 +%SystemRoot%\System32\net.exe start w32time >nul 2>&1 +%SystemRoot%\System32\sc.exe config w32time start= auto >nul 2>&1 +%SystemRoot%\System32\w32tm.exe /resync /force >nul 2>&1 + +:: Wait for the Splash Screen to load +:LOOP +:: Check if the Splash Screen is running +%SystemRoot%\system32\tasklist.exe | %SystemRoot%\system32\find.exe /i "enaTec_Installer" >nul 2>&1 +IF ERRORLEVEL 1 ( + :: Wait for 5 seconds + %SystemRoot%\system32\timeout.exe /T 5 /Nobreak >nul 2>&1 + :: Check again + GOTO LOOP +) ELSE ( + :: Splash Screen is running + GOTO SetLogHeader +) + +:SetLogHeader +ECHO ******************************************************************************** >%logfile_setup% +ECHO Started %Module% on %DATE:~0% - %TIME:~0,8% +ECHO For %COMPUTERNAME% by %USERDOMAIN%\%USERNAME% >>%logfile_setup% + +ECHO.>>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:SetPowerPlanToHighPerformance +ECHO Set Power Plan to High Performance +ECHO %TIME:~0,8% Set Power Plan to High Performance >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "c:\scripts\PowerShell\Set-PowerPlanToHighPerformance.ps1" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +:DisableCortanaSearchbar +ECHO Disable Cortana Searchbar +ECHO %TIME:~0,8% Disable Cortana Searchbar >>%logfile_setup% +"%SystemRoot%\System32\reg.exe" ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Search" /v SearchboxTaskbarMode /t REG_DWORD /d 0 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +ECHO.>>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:CreatePowerShellProfiles +ECHO Create plain PowerShell Profiles +ECHO %TIME:~0,8% Create plain PowerShell Profiles >>%logfile_setup% +start /MIN /WAIT "CleanupStockApps" %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "C:\scripts\PowerShell\New-PowerShellProfiles.ps1" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:ConfigureStorageSense +ECHO Configure Storage Sense +ECHO %TIME:~0,8% Configure Storage Sense >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Set-StorageSense.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:BootstrapTheUser +ECHO Bootstrap the User +ECHO %TIME:~0,8% Bootstrap the User >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Invoke-BootstrapUser.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:ApplyTweaksLocal +ECHO Apply tweaks local +ECHO %TIME:~0,8% Apply tweaks local >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\reg.exe" ADD HKU\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce /v BootstrapUser /t REG_SZ /d "powershell.exe -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command '$null = (C:\scripts\PowerShell\Invoke-BootstrapUser.ps1)'" /f >>%logfile_setup% 2>&1 + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:UpdateAllMicrosoftStoreApps +ECHO Update all Microsoft Store Apps +ECHO %TIME:~0,8% Update all Microsoft Store Apps >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Update-AllMicrosoftStoreApps.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:SetOneDriveToGetInsiderBuilds +ECHO Set OneDrive to get Insider builds +ECHO %TIME:~0,8% Set OneDrive to get Insider builds >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\reg.exe" add HKCU\Software\Microsoft\OneDrive /v EnableTeamTier_Internal /t REG_DWORD /d 1 /f >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:ForceOneDriveToUpdateAndRestart +ECHO Force OneDrive to update and restart +ECHO %TIME:~0,8% Force OneDrive to update and restart >>%logfile_setup% 2>&1 +C:\Windows\SysWOW64/OneDriveSetup.exe /update /restart /force >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:DownloadAndInstallLatestVersionOfMicrosoftTeams +ECHO Download and install latest version of Microsoft Teams +ECHO %TIME:~0,8% Download and install latest version of Microsoft Teams >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Install-LatestTeamsClient.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:EnableQoSForMicrosoftTeams +ECHO Enable QoS for Microsoft Teams +ECHO %TIME:~0,8% Enable QoS for Microsoft Teams >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Set-QoSForMicrosoftTeams.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:TweakTheFirewallForMicrosoftTeams +ECHO Tweak the Firewall for Microsoft Teams +ECHO %TIME:~0,8% Tweak the Firewall for Microsoft Teams >>%logfile_setup% 2>&1 +SC stop wsearch >nul 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Invoke-TweakTeamsClientFirewall.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:ConfigureMicrosoftDefender +ECHO Configure Microsoft Defender +ECHO %TIME:~0,8% Configure Microsoft Defender >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Optimize-MicrosoftDefenderExclusions.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:InstallSomePowerShellModules +ECHO Install some PowerShell Modules +ECHO %TIME:~0,8% Install some PowerShell Modules >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Install-PowerShellModules_required.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:InstallChocoWorkstationPackages +ECHO Install Choco Workstation packages +ECHO %TIME:~0,8% Install Choco Workstation packages >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(c:\scripts\PowerShell\Install-ChocoPackages_Workstation.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:InstallWinGetFromTheGitHubRepository +ECHO Install WinGet from the GitHub Repository +ECHO %TIME:~0,8% Install WinGet from the GitHub Repository >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Install-WingetFromRepositoryRelease.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:AutomateTheDriverUpdateProcess +ECHO Automate the driver update process +ECHO %TIME:~0,8% Automate the driver update process >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy Bypass -Command "(c:\scripts\PowerShell\Invoke-MSIntuneDriverUpdate.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:DesktopCleanup +ECHO Desktop Cleanup +ECHO %TIME:~0,8% Desktop Cleanup >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Remove-AllPublicDesktopLinks.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +ECHO Set the default Start menu +ECHO %TIME:~0,8% Set the default Start menu >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Set-DefaultStartMenu.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:DisableWindowsScriptHost +:: Turn off Windows Script Host (current user only) +ECHO Turn off Windows Script Host +ECHO %TIME:~0,8% Turn on Windows Script Host >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (New-ItemProperty -Path 'HKCU:\SOFTWARE\Microsoft\Windows Script Host\Settings' -Name Enabled -PropertyType DWord -Value 0 -Force -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:EncryptTheBootDriveWithBitLocker +ECHO Encrypt the Boot drive with BitLocker +ECHO %TIME:~0,8% Encrypt the Boot drive with BitLocker >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Enable-BitLockerEncryption.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:SaveBitLockerKeyToAzureAD +ECHO Save BitLocker Key to AzureAD +ECHO %TIME:~0,8% Save BitLocker Key to AzureAD >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Invoke-BackupBitLockerKeyToAAD.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:ApplyAllPendingMicrosoftUpdates +ECHO Apply all pending Microsoft updates +ECHO %TIME:~0,8% Apply all pending Microsoft updates >>%logfile_setup% 2>&1 +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "(C:\scripts\PowerShell\Install-AllMissingMicrosoftUpdates.ps1 -ErrorAction Continue)" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: DEFAULT +ECHO.>>%logfile_setup% 2>nul +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "$null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction SilentlyContinue)" >nul 2>&1 +SC stop wsearch >nul 2>&1 +:: DEFAULT + +:SetPowerPlanToAuto +ECHO Set Power Plan to Auto +ECHO %TIME:~0,8% Set Power Plan to Auto >>%logfile_setup% +"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "c:\scripts\PowerShell\Set-PowerPlanToAuto.ps1" >>%logfile_setup% 2>&1 +ECHO Errorlevel=%Errorlevel% >>%logfile_setup% 2>nul + +:: Go away +POPD >nul 2>&1 +CD / >nul 2>&1 + +ECHO %TIME:~0,8% Bootstrap and JumpStart finished >>%logfile_setup% +ECHO ******************************************************************************** >>%logfile_setup% +ECHO.>>%logfile_setup% 2>nul + +:: Initiate a restart +SHUTDOWN -r -t 5 >nul 2>&1 + +:: Final cleanup +IF EXIST c:\install\ rd /s /q c:\install\ >nul 2>&1 + +:: ******************************************************************************************************************** +:: +:: Changelog: +:: +:: 0.9.0: Internal Test +:: 1.0.0: Initial Release +:: +:: ******************************************************************************************************************** +:: +:: License: BSD 3-Clause License +:: +:: Copyright 2020, enabling Technology +:: All rights reserved. +:: +:: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the +:: following conditions are met: +:: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following +:: disclaimer. +:: 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the +:: following disclaimer in the documentation and/or other materials provided with the distribution. +:: 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote +:: products derived from this software without specific prior written permission. +:: +:: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +:: INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +:: DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +:: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +:: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +:: WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +:: USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +:: +:: ******************************************************************************************************************** +:: +:: Disclaimer: +:: - Use at your own risk, etc. +:: - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty +:: in any kind +:: - This is a third-party Software +:: - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its +:: subsidiaries in any way +:: - The Software is not supported by Microsoft Corp (MSFT) +:: - By using the Software, you agree to the License, Terms, and any Conditions declared and described above +:: - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +:: +:: ******************************************************************************************************************** diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/TeamViewerQS.exe b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/TeamViewerQS.exe new file mode 100644 index 0000000..87e613e Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/TeamViewerQS.exe differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/enaTec_Installer.exe b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/enaTec_Installer.exe new file mode 100644 index 0000000..db572d0 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/enaTec_Installer.exe differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/enaTec_Installer.exe.config b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/enaTec_Installer.exe.config new file mode 100644 index 0000000..85e07b1 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/enaTec_Installer.exe.config @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/logon.bgi b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/logon.bgi new file mode 100644 index 0000000..bc37764 Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/logon.bgi differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/sysinfo.exe b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/sysinfo.exe new file mode 100644 index 0000000..f03490d Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/sysinfo.exe differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/unison-fsmonitor.exe b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/unison-fsmonitor.exe new file mode 100644 index 0000000..fb374fb Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/unison-fsmonitor.exe differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/unison.exe b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/unison.exe new file mode 100644 index 0000000..3fb744b Binary files /dev/null and b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/Tools/unison.exe differ diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Cleanup_StockApps.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Cleanup_StockApps.ps1 new file mode 100644 index 0000000..38f6dd3 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Cleanup_StockApps.ps1 @@ -0,0 +1,250 @@ +#requires -Version 2.0 -RunAsAdministrator + +<# + .SYNOPSIS + Remove Windows 10 Stock Applications + + .DESCRIPTION + Remove Windows 10 Stock Applications + + .NOTES + Version 1.0.2 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Remove Windows 10 Stock Applications' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + #region AppList + $AllPackages = @( + 'Microsoft.Windows.Cortana', + '*Cortana*', 'Microsoft.Bing*', + 'Microsoft.Xbox*', + 'Microsoft.WindowsPhone', + '*Solitaire*', + 'Microsoft.People', + 'Microsoft.Zune*', + 'Microsoft.WindowsSoundRecorder', + 'microsoft.windowscommunicationsapps', + 'Microsoft.SkypeApp', + 'officehub', + '3dbuilder', + 'windowscamera', + '*Dell*', + '*Dropbox*', + '*Facebook*', + 'Microsoft.WindowsFeedbackHub', + 'Microsoft.Getstarted', + '*Autodesk*', + '*Keeper*', + '*McAfee*', + '*Minecraft*', + '*Netflix*', + 'Microsoft.MicrosoftOfficeHub', + 'Microsoft.OneConnect', + '*Plex*', + 'Microsoft.SkypeApp', + '*Solitaire*', + 'Microsoft.Office.Sway', + '*Twitter*', + '*DisneyMagicKingdom*', + '*Disney*', + '*HiddenCityMysteryofShadows*', + '*HiddenCity*', + 'Microsoft.YourPhone', + 'Microsoft.WindowsMaps', + 'Microsoft.Print3D', + 'Microsoft.MixedReality.Portal', + 'Microsoft.Microsoft3DViewer', + 'Microsoft.GetHelp', + 'Microsoft.MicrosoftStickyNotes', + 'Microsoft.Windows.Photos' + 'Microsoft.MSPaint' + ) + #endregion AppList +} + +process +{ + #region AppListLoop + foreach ($item in $AllPackages) + { + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + $paramRemoveAppxPackage = @{ + Confirm = $false + PreserveApplicationData = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $paramGetAppxPackage = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-AppxPackage @paramGetAppxPackage | Where-Object -FilterScript { + $_.name -like '*' + $item + '*' + } | Remove-AppxPackage @paramRemoveAppxPackage) + } + catch + { + Write-Verbose -Message 'Whoopsie' + } + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $paramRemoveAppxPackage = @{ + AllUsers = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $paramGetAppxPackage = @{ + AllUsers = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-AppxPackage @paramGetAppxPackage | Where-Object -FilterScript { + $_.name -like '*' + $item + '*' + } | Remove-AppxPackage @paramRemoveAppxPackage) + } + catch + { + Write-Verbose -Message 'Whoopsie' + } + + try + { + $paramRemoveAppxProvisionedPackage = @{ + Online = $true + AllUsers = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $paramGetAppxProvisionedPackage = @{ + Online = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-AppxProvisionedPackage @paramGetAppxProvisionedPackage | Where-Object -FilterScript { + $_.DisplayName -like '*' + $item + '*' + } | Remove-AppxProvisionedPackage @paramRemoveAppxProvisionedPackage) + } + catch + { + Write-Verbose -Message 'Whoopsie' + } + } + #endregion AppListLoop + + #region UninstallMcAfeeSecurity + $McAfeeSecurityApp = $null + + $paramGetChildItem = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' + ErrorAction = $SCT + WarningAction = $SCT + } + + $McAfeeSecurityApp = (Get-ChildItem @paramGetChildItem | ForEach-Object -Process { + $paramGetItemProperty = @{ + Path = $_.PSPath + ErrorAction = $SCT + WarningAction = $SCT + } + Get-ItemProperty @paramGetItemProperty + } | Where-Object -FilterScript { + $_ -match 'McAfee Security' + } | Select-Object -ExpandProperty UninstallString) + + if ($McAfeeSecurityApp) + { + $McAfeeSecurityApp = $McAfeeSecurityApp -Replace "$env:ProgramW6432\McAfee\MSC\mcuihost.exe", '' + + $paramStartProcess = @{ + FilePath = "$env:ProgramW6432\McAfee\MSC\mcuihost.exe" + ArgumentList = $McAfeeSecurityApp + Wait = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Start-Process @paramStartProcess) + } + #endregion UninstallMcAfeeSecurity +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Config-ChromeBrowsers.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Config-ChromeBrowsers.ps1 new file mode 100644 index 0000000..368885e --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Config-ChromeBrowsers.ps1 @@ -0,0 +1,483 @@ +#requires -Version 3.0 + +<# + .SYNOPSIS + Create a JSON based configuration for Chromium based Browsers + + .DESCRIPTION + Create and deploy a JSON based configuration for Chromium based Browsers + + .NOTES + For now, Chromium, Google Chrome, Microsoft Edge, and Microsoft Edge Beta are supported + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Create and deploy a JSON based configuration for Chromium based Browsers' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region Variables + $DefaultHome = 'http://www.google.com/ig' + $BrowserPath = $null + $MasterPreferenceFile = 'master_preferences' + #endregion Variables + + #region ChromePreferences + $ChromePreferences = [PSCustomObject]@{ } + $ChromePreferences | Add-Member -NotePropertyName homepage -NotePropertyValue $DefaultHome + $ChromePreferences | Add-Member -NotePropertyName homepage_is_newtabpage -NotePropertyValue $false + $ChromePreferences | Add-Member -NotePropertyName browser -NotePropertyValue ([PSCustomObject]@{ }) + $ChromePreferences.browser | Add-Member -NotePropertyName show_home_button -NotePropertyValue $true + $ChromePreferences | Add-Member -NotePropertyName session -NotePropertyValue ([PSCustomObject]@{ }) + $ChromePreferences.session | Add-Member -NotePropertyName restore_on_startup -NotePropertyValue 4 + $ChromePreferences.session | Add-Member -NotePropertyName startup_urls -NotePropertyValue (@($DefaultHome)) + $ChromePreferences | Add-Member -NotePropertyName bookmark_bar -NotePropertyValue ([PSCustomObject]@{ }) + $ChromePreferences.bookmark_bar | Add-Member -NotePropertyName show_on_all_tabs -NotePropertyValue $true + $ChromePreferences | Add-Member -NotePropertyName sync_promo -NotePropertyValue ([PSCustomObject]@{ }) + $ChromePreferences.sync_promo | Add-Member -NotePropertyName show_on_first_run_allowed -NotePropertyValue $false + $ChromePreferences | Add-Member -NotePropertyName distribution -NotePropertyValue ([PSCustomObject]@{ }) + $ChromePreferences.distribution | Add-Member -NotePropertyName skip_first_run_ui -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName import_bookmarks -NotePropertyValue $false + $ChromePreferences.distribution | Add-Member -NotePropertyName import_history -NotePropertyValue $false + $ChromePreferences.distribution | Add-Member -NotePropertyName import_search_engine -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName suppress_first_run_bubble -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName create_all_shortcuts -NotePropertyValue $false + $ChromePreferences.distribution | Add-Member -NotePropertyName do_not_launch_chrome -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName do_not_register_for_update_launch -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName do_not_create_desktop_shortcut -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName do_not_create_quick_launch_shortcut -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName do_not_create_taskbar_shortcut -NotePropertyValue $false + $ChromePreferences.distribution | Add-Member -NotePropertyName make_chrome_default -NotePropertyValue $false + $ChromePreferences.distribution | Add-Member -NotePropertyName ping_delay -NotePropertyValue 60 + $ChromePreferences.distribution | Add-Member -NotePropertyName make_chrome_default_for_user -NotePropertyValue $false + $ChromePreferences.distribution | Add-Member -NotePropertyName suppress_first_run_default_browser_prompt -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName system_level -NotePropertyValue $true + $ChromePreferences.distribution | Add-Member -NotePropertyName verbose_logging -NotePropertyValue $false + $ChromePreferences.distribution | Add-Member -NotePropertyName allow_downgrade -NotePropertyValue $false + $ChromePreferences | Add-Member -NotePropertyName first_run_tabs -NotePropertyValue ([PSObject]@($DefaultHome)) + $paramConvertToJson = @{ + Depth = 10 + Compress = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $ChromePreferencesJson = ($ChromePreferences | ConvertTo-Json @paramConvertToJson) + #endregion ChromePreferences + + #region EdgePreferences + $EdgePreferences = [PSCustomObject]@{ } + $EdgePreferences | Add-Member -NotePropertyName homepage_is_newtabpage -NotePropertyValue $false + $EdgePreferences | Add-Member -NotePropertyName browser -NotePropertyValue ([PSCustomObject]@{ }) + $EdgePreferences.browser | Add-Member -NotePropertyName show_home_button -NotePropertyValue $true + $EdgePreferences | Add-Member -NotePropertyName session -NotePropertyValue ([PSCustomObject]@{ }) + $EdgePreferences.session | Add-Member -NotePropertyName restore_on_startup -NotePropertyValue 4 + $EdgePreferences | Add-Member -NotePropertyName bookmark_bar -NotePropertyValue ([PSCustomObject]@{ }) + $EdgePreferences.bookmark_bar | Add-Member -NotePropertyName show_on_all_tabs -NotePropertyValue $true + $EdgePreferences | Add-Member -NotePropertyName sync_promo -NotePropertyValue ([PSCustomObject]@{ }) + $EdgePreferences.sync_promo | Add-Member -NotePropertyName show_on_first_run_allowed -NotePropertyValue $false + $EdgePreferences | Add-Member -NotePropertyName distribution -NotePropertyValue ([PSCustomObject]@{ }) + $EdgePreferences.distribution | Add-Member -NotePropertyName skip_first_run_ui -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName import_bookmarks -NotePropertyValue $false + $EdgePreferences.distribution | Add-Member -NotePropertyName import_history -NotePropertyValue $false + $EdgePreferences.distribution | Add-Member -NotePropertyName import_search_engine -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName suppress_first_run_bubble -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName create_all_shortcuts -NotePropertyValue $false + $EdgePreferences.distribution | Add-Member -NotePropertyName do_not_launch_chrome -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName do_not_register_for_update_launch -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName do_not_create_desktop_shortcut -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName do_not_create_quick_launch_shortcut -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName do_not_create_taskbar_shortcut -NotePropertyValue $false + $EdgePreferences.distribution | Add-Member -NotePropertyName make_chrome_default -NotePropertyValue $false + $EdgePreferences.distribution | Add-Member -NotePropertyName ping_delay -NotePropertyValue 60 + $EdgePreferences.distribution | Add-Member -NotePropertyName make_chrome_default_for_user -NotePropertyValue $false + $EdgePreferences.distribution | Add-Member -NotePropertyName suppress_first_run_default_browser_prompt -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName system_level -NotePropertyValue $true + $EdgePreferences.distribution | Add-Member -NotePropertyName verbose_logging -NotePropertyValue $false + $EdgePreferences.distribution | Add-Member -NotePropertyName allow_downgrade -NotePropertyValue $false + $paramConvertToJson = @{ + Depth = 10 + Compress = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $EdgePreferencesJson = ($EdgePreferences | ConvertTo-Json @paramConvertToJson) + #endregion EdgePreferences +} + +process +{ + #region Chromium + $BrowserPath = "$env:ProgramW6432\Chromium\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Chromium X64' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $ChromePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $BrowserPath = "${env:ProgramFiles(x86)}\Chromium\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Chromium X86' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $ChromePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion Chromium + + #region GoogleChrome + $BrowserPath = "$env:ProgramW6432\Google\Chrome\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Google Chrome X64' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $ChromePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $BrowserPath = "${env:ProgramFiles(x86)}\Google\Chrome\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Google Chrome X86' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $ChromePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion GoogleChrome + + #region MicrosoftEdge + $BrowserPath = "$env:ProgramW6432\Microsoft\Edge\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Microsoft Edge Release X64' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $EdgePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $BrowserPath = "${env:ProgramFiles(x86)}\Microsoft\Edge\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Microsoft Edge Release X86' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $EdgePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion MicrosoftEdge + + #region MicrosoftEdgeBeta + $BrowserPath = "$env:ProgramW6432\Microsoft\Edge Beta\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Microsoft Edge Beta X64' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $EdgePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $BrowserPath = "${env:ProgramFiles(x86)}\Microsoft\Edge Beta\Application\" + + $paramTestPath = @{ + Path = $BrowserPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + Write-Verbose -Message 'Configure Microsoft Edge Beta X86' + + $paramTestPath = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath ) + { + $paramRemoveItem = @{ + Path = ($BrowserPath + $MasterPreferenceFile) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $paramNewItem = @{ + Path = $BrowserPath + Name = $MasterPreferenceFile + Value = $EdgePreferencesJson + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion MicrosoftEdgeBeta +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Disable-ContentDeliveryManager.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Disable-ContentDeliveryManager.ps1 new file mode 100644 index 0000000..545b6e7 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Disable-ContentDeliveryManager.ps1 @@ -0,0 +1,97 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Disable Windows Content Delivery Management + + .DESCRIPTION + Disable Windows Content Delivery Management + + .EXAMPLE + PS C:\> .\Disable-ContentDeliveryManager.ps1 + + .NOTES + Requested Helper + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + Write-Output -InputObject 'Disable Windows Content Delivery Management' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + $ContentDeliveryManagerPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager' + #endregion +} + +process +{ + $paramGetItem = @{ + Path = $ContentDeliveryManagerPath + Force = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $ContentDeliveryManagerKeys = (Get-Item @paramGetItem) + + $ContentDeliveryManagerKeys.GetValueNames() | ForEach-Object -Process { + if ($ContentDeliveryManagerKeys.GetValueKind($_) -eq 'DWord') + { + $paramSetItemProperty = @{ + Path = $ContentDeliveryManagerPath + Name = $_ + Value = 0 + Force = $true + WhatIf = $true + ErrorAction = $SCT + WarningAction = $SCT + Confirm = $false + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + } +} + +end +{ + exit (0) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Enable-BitLockerEncryption.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Enable-BitLockerEncryption.ps1 new file mode 100644 index 0000000..927d828 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Enable-BitLockerEncryption.ps1 @@ -0,0 +1,964 @@ +#requires -Version 5.0 -RunAsAdministrator + +<# + .SYNOPSIS + Enable BitLocker with both TPM and recovery password key protectors on Windows 10 devices. + + .DESCRIPTION + Enable BitLocker with both TPM and recovery password key protectors on Windows 10 devices. + + .PARAMETER EncryptionMethod + Define the encryption method to be used when enabling BitLocker. + + .PARAMETER OperationalMode + Set the operational mode of this script. + + .PARAMETER CompanyName + Set the company name to be used as registry root when running in Backup mode. + + .NOTES + Version 1.0.1 + + Adopted version of Enable-BitLockerEncryption.ps1 from Nickolaj Andersen (@NickolajA) +#> +[CmdletBinding(SupportsShouldProcess)] +param ( + [ValidateNotNullOrEmpty()] + [ValidateSet('Aes128', 'Aes256', 'XtsAes128', 'XtsAes256')] + [string] + $EncryptionMethod = 'XtsAes256', + [ValidateNotNullOrEmpty()] + [ValidateSet('Encrypt', 'Backup')] + [string] + $OperationalMode = 'Encrypt', + [ValidateNotNullOrEmpty()] + [string] + $CompanyName = 'enabling Technology' +) + +begin +{ + Write-Output -InputObject 'Enable BitLocker with both TPM and recovery password key protectors' + + #region + $STP = 'Stop' + $SCT = 'SilentlyContinue' + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + #region + function Write-LogEntry + { + <# + .SYNOPSIS + Describe purpose of "Write-LogEntry" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER Value + Describe parameter -Value. + + .PARAMETER Severity + Describe parameter -Severity. + + .EXAMPLE + Write-LogEntry -Value Value -Severity Value + Describe what this call does + + .NOTES + Place additional notes here. + + .LINK + URLs to related sites + The first link is opened by Get-Help -Online Write-LogEntry + + .INPUTS + List of input types that are accepted by this function. + + .OUTPUTS + List of output types produced by this function. + #> + param ( + [parameter(Mandatory, HelpMessage = 'Value added to the log file.')] + [ValidateNotNullOrEmpty()] + [string] + $Value, + [parameter(Mandatory, HelpMessage = 'Severity for the log entry. 1 for Informational, 2 for Warning and 3 for Error.')] + [ValidateNotNullOrEmpty()] + [ValidateSet('1', '2', '3')] + [string] + $Severity + ) + begin + { + $SCT = 'SilentlyContinue' + } + + process + { + # Determine log file location + $paramJoinPath = @{ + Path = (Join-Path -Path $env:windir -ChildPath 'Temp' -ErrorAction $SCT) + ChildPath = 'Enable-BitLockerEncryption.log' + ErrorAction = $SCT + } + $LogFilePath = (Join-Path @paramJoinPath) + + # Construct time stamp for log entry + $paramTestPath = @{ + Path = 'variable:global:TimezoneBias' + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + [string]$global:TimezoneBias = [TimeZoneInfo]::Local.GetUtcOffset((Get-Date)).TotalMinutes + + if ($TimezoneBias -match '^-') + { + $TimezoneBias = $TimezoneBias.Replace('-', '+') + } + else + { + $TimezoneBias = '-' + $TimezoneBias + } + } + + $Time = -join @((Get-Date -Format 'HH:mm:ss.fff'), $TimezoneBias) + + # Construct date for log entry + $Date = (Get-Date -Format 'MM-dd-yyyy') + + # Construct context for log entry + $Context = $([Security.Principal.WindowsIdentity]::GetCurrent().Name) + + # Construct final log entry + $LogText = "" + + # Add value to log file + try + { + $paramOutFile = @{ + Append = $true + NoClobber = $true + Encoding = 'Default' + FilePath = $LogFilePath + ErrorAction = 'Stop' + } + $null = ($LogText | Out-File @paramOutFile) + } + catch + { + Write-Warning -Message "Unable to append log entry to Enable-BitLockerEncryption.log file. Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)" + } + } + } + + function Invoke-Executable + { + <# + .SYNOPSIS + Describe purpose of "Invoke-Executable" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER FilePath + Describe parameter -FilePath. + + .PARAMETER Arguments + Describe parameter -Arguments. + + .EXAMPLE + Invoke-Executable -FilePath Value -Arguments Value + Describe what this call does + + .NOTES + Place additional notes here. + + .LINK + URLs to related sites + The first link is opened by Get-Help -Online Invoke-Executable + + .INPUTS + List of input types that are accepted by this function. + + .OUTPUTS + List of output types produced by this function. + #> + param ( + [parameter(Mandatory, HelpMessage = 'Specify the file name or path of the executable to be invoked, including the extension')] + [ValidateNotNullOrEmpty()] + [string] + $FilePath, + [ValidateNotNull()] + [string] + $Arguments + ) + + process + { + # Construct a hash-table for default parameter splatting + $SplatArgs = @{ + FilePath = $FilePath + NoNewWindow = $true + Passthru = $true + RedirectStandardOutput = 'null.txt' + ErrorAction = 'Stop' + } + + # Add ArgumentList param if present + if (-not ([string]::IsNullOrEmpty($Arguments))) + { + $SplatArgs.Add('ArgumentList', $Arguments) + } + + # Invoke executable and wait for process to exit + try + { + $Invocation = (Start-Process @SplatArgs) + $Handle = $Invocation.Handle + $Invocation.WaitForExit() + + # Remove redirected output file + $paramRemoveItem = @{ + Path = (Join-Path -Path $PSScriptRoot -ChildPath 'null.txt' -ErrorAction Continue) + Force = $true + } + $null = (Remove-Item @paramRemoveItem) + } + catch + { + Write-Warning -Message $_.Exception.Message + break + } + + return $Invocation.ExitCode + } + } + + function Test-RegistryValue + { + <# + .SYNOPSIS + Describe purpose of "Test-RegistryValue" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER Path + Describe parameter -Path. + + .PARAMETER Name + Describe parameter -Name. + + .EXAMPLE + Test-RegistryValue -Path Value -Name Value + Describe what this call does + + .NOTES + Place additional notes here. + + .LINK + URLs to related sites + The first link is opened by Get-Help -Online Test-RegistryValue + + .INPUTS + List of input types that are accepted by this function. + + .OUTPUTS + List of output types produced by this function. + #> + param ( + [parameter(Mandatory, HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [string] + $Path, + [ValidateNotNullOrEmpty()] + [string] + $Name + ) + + begin + { + # If item property value exists return True, else catch the failure and return False + $STP = 'Stop' + } + + process + { + try + { + if ($PSBoundParameters['Name']) + { + $paramGetItemProperty = @{ + Path = $Path + ErrorAction = $STP + } + $Existence = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty $Name -ErrorAction $STP) + } + else + { + $paramGetItemProperty = @{ + Path = $Path + ErrorAction = $STP + } + $Existence = (Get-ItemProperty @paramGetItemProperty) + } + + if ($Existence) + { + return $true + } + } + catch + { + return $false + } + } + } + + function Set-RegistryValue + { + <# + .SYNOPSIS + Describe purpose of "Set-RegistryValue" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER Path + Describe parameter -Path. + + .PARAMETER Name + Describe parameter -Name. + + .PARAMETER Value + Describe parameter -Value. + + .EXAMPLE + Set-RegistryValue -Path Value -Name Value -Value Value + Describe what this call does + + .NOTES + Place additional notes here. + + .LINK + URLs to related sites + The first link is opened by Get-Help -Online Set-RegistryValue + + .INPUTS + List of input types that are accepted by this function. + + .OUTPUTS + List of output types produced by this function. + #> + param ( + [parameter(Mandatory, HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [string] + $Path, + [parameter(Mandatory, HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [string] + $Name, + [parameter(Mandatory, HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [string] + $Value + ) + begin + { + $SCT = 'SilentlyContinue' + $STP = 'Stop' + } + + process + { + try + { + $paramGetItemProperty = @{ + Path = $Path + Name = $Name + ErrorAction = $SCT + } + $RegistryValue = (Get-ItemProperty @paramGetItemProperty) + + if ($RegistryValue) + { + $paramSetItemProperty = @{ + Path = $Path + Name = $Name + Value = $Value + Force = $true + ErrorAction = $STP + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + else + { + $paramNewItemProperty = @{ + Path = $Path + Name = $Name + PropertyType = 'String' + Value = $Value + Force = $true + ErrorAction = $STP + } + $null = (New-ItemProperty @paramNewItemProperty) + } + } + catch + { + Write-LogEntry -Value "Failed to create or update registry value '$($Name)' in '$($Path)'. Error message: $($_.Exception.Message)" -Severity 3 + } + } + } + #endregion +} + +process +{ + # Check if we're running as a 64-bit process or not + if (-not [Environment]::Is64BitProcess) + { + # Get the sysnative path for powershell.exe + $paramJoinPath = @{ + Path = ($PSHOME.ToLower().Replace('syswow64', 'sysnative')) + ChildPath = 'powershell.exe' + } + $SysNativePowerShell = (Join-Path @paramJoinPath) + + # Construct new ProcessStartInfo object to restart powershell.exe as a 64-bit process and re-run scipt + $ProcessStartInfo = (New-Object -TypeName System.Diagnostics.ProcessStartInfo) + $ProcessStartInfo.FileName = $SysNativePowerShell + $ProcessStartInfo.Arguments = "-ExecutionPolicy Bypass -File ""$($PSCommandPath)""" + $ProcessStartInfo.RedirectStandardOutput = $true + $ProcessStartInfo.RedirectStandardError = $true + $ProcessStartInfo.UseShellExecute = $false + $ProcessStartInfo.WindowStyle = 'Hidden' + $ProcessStartInfo.CreateNoWindow = $true + + # Instatiate the new 64-bit process + $Process = [Diagnostics.Process]::Start($ProcessStartInfo) + + # Read standard error output to determine if the 64-bit script process somehow failed + $ErrorOutput = $Process.StandardError.ReadToEnd() + + if ($ErrorOutput) + { + Write-Error -Message $ErrorOutput + } + } + else + { + try + { + # Define the company registry root key + $RegistryRootPath = "HKLM:\SOFTWARE\$($CompanyName)" + + if (-not (Test-RegistryValue -Path $RegistryRootPath)) + { + Write-LogEntry -Value 'Attempting to create registry root path for recovery password escrow results' -Severity 1 + + $paramNewItem = @{ + Path = $RegistryRootPath + ItemType = 'Directory' + Force = $true + ErrorAction = $STP + } + $null = (New-Item @paramNewItem) + } + } + catch + { + Write-LogEntry -Value "An error occurred while creating registry root item '$($RegistryRootPath)'. Error message: $($_.Exception.Message)" -Severity 3 + } + + # Switch execution context depending on selected operational mode for the script as parameter input + switch ($OperationalMode) + { + 'Encrypt' + { + Write-LogEntry -Value "Current operational mode for script: $($OperationalMode)" -Severity 1 + + try + { + try + { + # Check if TPM chip is currently owned, if not take ownership + $paramGetWmiObject = @{ + Namespace = 'root\cimv2\Security\MicrosoftTPM' + Class = 'Win32_TPM' + } + $TPMClass = (Get-WmiObject @paramGetWmiObject) + $IsTPMOwned = $TPMClass.IsOwned().IsOwned + + if ($IsTPMOwned -eq $false) + { + Write-LogEntry -Value "TPM chip is currently not owned, value from WMI class method 'IsOwned' was: $($IsTPMOwned)" -Severity 1 + + # Generate a random pass phrase to be used when taking ownership of TPM chip + $NewPassPhrase = (New-Guid).Guid.Replace('-', '').SubString(0, 14) + + # Construct owner auth encoded string + $NewOwnerAuth = $TPMClass.ConvertToOwnerAuth($NewPassPhrase).OwnerAuth + + # Attempt to take ownership of TPM chip + $Invocation = $TPMClass.TakeOwnership($NewOwnerAuth) + + if ($Invocation.ReturnValue -eq 0) + { + Write-LogEntry -Value 'TPM chip ownership was successfully taken' -Severity 1 + } + else + { + Write-LogEntry -Value "Failed to take ownership of TPM chip, return value from invocation: $($Invocation.ReturnValue)" -Severity 3 + } + } + else + { + Write-LogEntry -Value 'TPM chip is currently owned, will not attempt to take ownership' -Severity 1 + } + } + catch + { + Write-LogEntry -Value "An error occurred while taking ownership of TPM chip. Error message: $($_.Exception.Message)" -Severity 3 + } + + try + { + # Retrieve the current encryption status of the operating system drive + Write-LogEntry -Value 'Attempting to retrieve the current encryption status of the operating system drive' -Severity 1 + + $paramGetBitLockerVolume = @{ + MountPoint = $env:SystemRoot + ErrorAction = $STP + } + $BitLockerOSVolume = (Get-BitLockerVolume @paramGetBitLockerVolume) + + if ($BitLockerOSVolume) + { + # Determine whether BitLocker is turned on or off + if (($BitLockerOSVolume.VolumeStatus -like 'FullyDecrypted') -or ($BitLockerOSVolume.KeyProtector.Count -eq 0)) + { + Write-LogEntry -Value "Current encryption status of the operating system drive was detected as: $($BitLockerOSVolume.VolumeStatus)" -Severity 1 + + try + { + # Enable BitLocker with TPM key protector + Write-LogEntry -Value "Attempting to enable BitLocker protection with TPM key protector for mount point: $($env:SystemRoot)" -Severity 1 + + $paramEnableBitLocker = @{ + MountPoint = $BitLockerOSVolume.MountPoint + TpmProtector = $true + UsedSpaceOnly = $true + EncryptionMethod = $EncryptionMethod + SkipHardwareTest = $true + ErrorAction = $STP + } + $null = (Enable-BitLocker @paramEnableBitLocker) + } + catch + { + Write-LogEntry -Value "An error occurred while enabling BitLocker with TPM key protector for mount point '$($env:SystemRoot)'. Error message: $($_.Exception.Message)" -Severity 3 + } + + try + { + # Enable BitLocker with recovery password key protector + Write-LogEntry -Value "Attempting to enable BitLocker protection with recovery password key protector for mount point: $($env:SystemRoot)" -Severity 1 + + $paramEnableBitLocker = @{ + MountPoint = $BitLockerOSVolume.MountPoint + RecoveryPasswordProtector = $true + UsedSpaceOnly = $true + EncryptionMethod = $EncryptionMethod + SkipHardwareTest = $true + ErrorAction = $STP + } + $null = (Enable-BitLocker @paramEnableBitLocker) + } + catch + { + Write-LogEntry -Value "An error occurred while enabling BitLocker with recovery password key protector for mount point '$($env:SystemRoot)'. Error message: $($_.Exception.Message)" -Severity 3 + } + } + elseif (($BitLockerOSVolume.VolumeStatus -like 'FullyEncrypted') -or ($BitLockerOSVolume.VolumeStatus -like 'UsedSpaceOnly')) + { + Write-LogEntry -Value "Current encryption status of the operating system drive was detected as: $($BitLockerOSVolume.VolumeStatus)" -Severity 1 + Write-LogEntry -Value 'Validating that all desired key protectors are enabled' -Severity 1 + + # Validate that not only the TPM protector is enabled, add recovery password protector + if ($BitLockerOSVolume.KeyProtector.Count -lt 2) + { + if ($BitLockerOSVolume.KeyProtector.KeyProtectorType -like 'Tpm') + { + Write-LogEntry -Value 'Recovery password key protector is not present' -Severity 1 + + try + { + # Enable BitLocker with TPM key protector + Write-LogEntry -Value "Attempting to enable BitLocker protection with recovery password key protector for mount point: $($env:SystemRoot)" -Severity 1 + + $paramEnableBitLocker = @{ + MountPoint = $BitLockerOSVolume.MountPoint + RecoveryPasswordProtector = $true + UsedSpaceOnly = $true + EncryptionMethod = $EncryptionMethod + SkipHardwareTest = $true + ErrorAction = $STP + } + $null = (Enable-BitLocker @paramEnableBitLocker) + } + catch + { + Write-LogEntry -Value "An error occurred while enabling BitLocker with TPM key protector for mount point '$($env:SystemRoot)'. Error message: $($_.Exception.Message)" -Severity 3 + } + } + + if ($BitLockerOSVolume.KeyProtector.KeyProtectorType -like 'RecoveryPassword') + { + Write-LogEntry -Value 'TPM key protector is not present' -Severity 1 + + try + { + # Add BitLocker recovery password key protector + Write-LogEntry -Value "Attempting to enable BitLocker protection with TPM key protector for mount point: $($env:SystemRoot)" -Severity 1 + + $paramEnableBitLocker = @{ + MountPoint = $BitLockerOSVolume.MountPoint + TpmProtector = $true + UsedSpaceOnly = $true + EncryptionMethod = $EncryptionMethod + SkipHardwareTest = $true + ErrorAction = $STP + } + $null = (Enable-BitLocker @paramEnableBitLocker) + } + catch + { + Write-LogEntry -Value "An error occurred while enabling BitLocker with recovery password key protector for mount point '$($env:SystemRoot)'. Error message: $($_.Exception.Message)" -Severity 3 + } + } + } + else + { + # BitLocker is in wait state + Invoke-Executable -FilePath 'manage-bde.exe' -Arguments "-On $($BitLockerOSVolume.MountPoint) -UsedSpaceOnly" + } + } + else + { + Write-LogEntry -Value "Current encryption status of the operating system drive was detected as: $($BitLockerOSVolume.VolumeStatus)" -Severity 1 + } + + # Validate that previous configuration was successful and all key protectors have been enabled and encryption is on + $paramGetBitLockerVolume = @{ + MountPoint = $env:SystemRoot + } + $BitLockerOSVolume = (Get-BitLockerVolume @paramGetBitLockerVolume) + + # Wait for encryption to complete + if ($BitLockerOSVolume.VolumeStatus -like 'EncryptionInProgress') + { + do + { + $paramGetBitLockerVolume = @{ + MountPoint = $env:SystemRoot + } + $BitLockerOSVolume = (Get-BitLockerVolume @paramGetBitLockerVolume) + + Write-LogEntry -Value "Current encryption percentage progress: $($BitLockerOSVolume.EncryptionPercentage)" -Severity 1 + Write-LogEntry -Value 'Waiting for BitLocker encryption progress to complete, sleeping for 15 seconds' -Severity 1 + + Start-Sleep -Seconds 15 + } + until ($BitLockerOSVolume.EncryptionPercentage -eq 100) + + Write-LogEntry -Value 'Encryption of operating system drive has now completed' -Severity 1 + } + + if (($BitLockerOSVolume.VolumeStatus -like 'FullyEncrypted') -and ($BitLockerOSVolume.KeyProtector.Count -eq 2)) + { + try + { + # Attempt to backup recovery password to Azure AD device object + Write-LogEntry -Value 'Attempting to backup recovery password to Azure AD device object' -Severity 1 + + $RecoveryPasswordKeyProtector = $BitLockerOSVolume.KeyProtector | Where-Object { + $_.KeyProtectorType -like 'RecoveryPassword' + } + + if ($RecoveryPasswordKeyProtector) + { + $paramBackupToAADBitLockerKeyProtector = @{ + MountPoint = $BitLockerOSVolume.MountPoint + KeyProtectorId = $RecoveryPasswordKeyProtector.KeyProtectorId + ErrorAction = $STP + } + $null = (BackupToAAD-BitLockerKeyProtector @paramBackupToAADBitLockerKeyProtector) + + Write-LogEntry -Value 'Successfully backed up recovery password details' -Severity 1 + } + else + { + Write-LogEntry -Value 'Unable to determine proper recovery password key protector for backing up of recovery password details' -Severity 2 + } + } + catch + { + Write-LogEntry -Value "An error occurred while attempting to backup recovery password to Azure AD. Error message: $($_.Exception.Message)" -Severity 3 + + # Copy executing script to system temporary directory + Write-LogEntry -Value 'Attempting to copy executing script to system temporary directory' -Severity 1 + + $paramJoinPath = @{ + Path = $env:SystemRoot + ChildPath = 'Temp' + } + $SystemTemp = (Join-Path @paramJoinPath) + + $paramTestPath = @{ + Path = (Join-Path -Path $SystemTemp -ChildPath "$($MyInvocation.MyCommand.Name)") + PathType = 'Leaf' + } + if (-not (Test-Path @paramTestPath)) + { + try + { + # Copy executing script + Write-LogEntry -Value 'Copying executing script to staging folder for scheduled task usage' -Severity 1 + + $paramCopyItem = @{ + Path = $MyInvocation.MyCommand.Definition + Destination = $SystemTemp + ErrorAction = $STP + } + $null = (Copy-Item @paramCopyItem) + + try + { + # Create escrow scheduled task to backup recovery password to Azure AD at a later time + $paramNewScheduledTaskAction = @{ + Execute = 'powershell.exe' + Argument = "-ExecutionPolicy Bypass -NoProfile -File $($SystemTemp)\$($MyInvocation.MyCommand.Name) -OperationalMode Backup" + ErrorAction = $STP + } + $TaskAction = (New-ScheduledTaskAction @paramNewScheduledTaskAction) + + $paramNewScheduledTaskTrigger = @{ + AtLogOn = $true + ErrorAction = $STP + } + $TaskTrigger = (New-ScheduledTaskTrigger @paramNewScheduledTaskTrigger) + + $paramNewScheduledTaskSettingsSet = @{ + AllowStartIfOnBatteries = $true + Hidden = $true + DontStopIfGoingOnBatteries = $true + Compatibility = 'Win8' + RunOnlyIfNetworkAvailable = $true + MultipleInstances = 'IgnoreNew' + ErrorAction = $STP + } + $TaskSettings = (New-ScheduledTaskSettingsSet @paramNewScheduledTaskSettingsSet) + + $paramNewScheduledTaskPrincipal = @{ + UserId = 'NT AUTHORITY\SYSTEM' + LogonType = 'ServiceAccount' + RunLevel = 'Highest' + ErrorAction = $STP + } + $TaskPrincipal = (New-ScheduledTaskPrincipal @paramNewScheduledTaskPrincipal) + + $paramNewScheduledTask = @{ + Action = $TaskAction + Principal = $TaskPrincipal + Settings = $TaskSettings + Trigger = $TaskTrigger + ErrorAction = $STP + } + $ScheduledTask = (New-ScheduledTask @paramNewScheduledTask) + + $paramRegisterScheduledTask = @{ + InputObject = $ScheduledTask + TaskName = 'Backup BitLocker Recovery Password to Azure AD' + TaskPath = '\Microsoft' + ErrorAction = $STP + } + $null = (Register-ScheduledTask @paramRegisterScheduledTask) + + try + { + # Attempt to create BitLocker recovery password escrow registry value + $paramTestRegistryValue = @{ + Path = $RegistryRootPath + Name = 'BitLockerEscrowResult' + } + if (-not (Test-RegistryValue @paramTestRegistryValue)) + { + Write-LogEntry -Value "Setting initial 'BitLockerEscrowResult' registry value to: None" -Severity 1 + + $paramSetRegistryValue = @{ + Path = $RegistryRootPath + Name = 'BitLockerEscrowResult' + Value = 'None' + } + $null = (Set-RegistryValue @paramSetRegistryValue) + } + } + catch + { + Write-LogEntry -Value "Unable to register scheduled task for backup of recovery password. Error message: $($_.Exception.Message)" -Severity 3 + } + } + catch + { + Write-LogEntry -Value "Unable to register scheduled task for backup of recovery password. Error message: $($_.Exception.Message)" -Severity 3 + } + } + catch + { + Write-LogEntry -Value "Unable to stage script in system temporary directory for scheduled task. Error message: $($_.Exception.Message)" -Severity 3 + } + } + } + } + else + { + Write-LogEntry -Value 'Validation of current encryption status for operating system drive was not successful' -Severity 2 + Write-LogEntry -Value "Current volume status for mount point '$($BitLockerOSVolume.MountPoint)': $($BitLockerOSVolume.VolumeStatus)" -Severity 2 + Write-LogEntry -Value "Count of enabled key protectors for volume: $($BitLockerOSVolume.KeyProtector.Count)" -Severity 2 + } + } + else + { + Write-LogEntry -Value 'Current encryption status query returned an empty result, this was not expected at this point' -Severity 2 + } + } + catch + { + Write-LogEntry -Value "An error occurred while retrieving the current encryption status of operating system drive. Error message: $($_.Exception.Message)" -Severity 3 + } + } + catch + { + Write-LogEntry -Value "An error occurred while importing the BitLocker module. Error message: $($_.Exception.Message)" -Severity 3 + } + } + 'Backup' + { + Write-LogEntry -Value "Current operational mode for script: $($OperationalMode)" -Severity 1 + + # Retrieve the current encryption status of the operating system drive + $paramGetBitLockerVolume = @{ + MountPoint = $env:SystemRoot + } + $BitLockerOSVolume = (Get-BitLockerVolume @paramGetBitLockerVolume) + + # Attempt to backup recovery password to Azure AD device object if volume is encrypted + if (($BitLockerOSVolume.VolumeStatus -like 'FullyEncrypted') -and ($BitLockerOSVolume.KeyProtector.Count -eq 2)) + { + try + { + $paramGetItemPropertyValue = @{ + Path = $RegistryRootPath + Name = 'BitLockerEscrowResult' + ErrorAction = $STP + } + $BitLockerEscrowResultsValue = (Get-ItemPropertyValue @paramGetItemPropertyValue) + + if ($BitLockerEscrowResultsValue -match 'None|False') + { + try + { + Write-LogEntry -Value 'Attempting to backup recovery password to Azure AD device object' -Severity 1 + + $RecoveryPasswordKeyProtector = $BitLockerOSVolume.KeyProtector | Where-Object { + $_.KeyProtectorType -like 'RecoveryPassword' + } + + if ($RecoveryPasswordKeyProtector) + { + $paramBackupToAADBitLockerKeyProtector = @{ + MountPoint = $BitLockerOSVolume.MountPoint + KeyProtectorId = $RecoveryPasswordKeyProtector.KeyProtectorId + ErrorAction = $STP + } + $null = (BackupToAAD-BitLockerKeyProtector @paramBackupToAADBitLockerKeyProtector) + + $paramSetRegistryValue = @{ + Path = $RegistryRootPath + Name = 'BitLockerEscrowResult' + Value = 'True' + } + $null = (Set-RegistryValue @paramSetRegistryValue) + + Write-LogEntry -Value 'Successfully backed up recovery password details' -Severity 1 + } + else + { + Write-LogEntry -Value 'Unable to determine proper recovery password key protector for backing up of recovery password details' -Severity 2 + } + } + catch + { + Write-LogEntry -Value "An error occurred while attempting to backup recovery password to Azure AD. Error message: $($_.Exception.Message)" -Severity 3 + + $paramSetRegistryValue = @{ + Path = $RegistryRootPath + Name = 'BitLockerEscrowResult' + Value = 'False' + } + $null = (Set-RegistryValue @paramSetRegistryValue) + } + } + else + { + Write-LogEntry -Value "Value for 'BitLockerEscrowResults' was '$($BitLockerEscrowResultsValue)', will not attempt to backup recovery password once more" -Severity 1 + + try + { + # Disable scheduled task + $paramGetScheduledTask = @{ + TaskName = 'Backup BitLocker Recovery Password to Azure AD' + ErrorAction = $STP + } + $ScheduledTask = (Get-ScheduledTask @paramGetScheduledTask) + + $paramDisableScheduledTask = @{ + InputObject = $ScheduledTask + ErrorAction = $STP + } + $null = (Disable-ScheduledTask @paramDisableScheduledTask) + + Write-LogEntry -Value "Successfully disabled scheduled task named 'Backup BitLocker Recovery Password to Azure AD'" -Severity 1 + } + catch + { + Write-LogEntry -Value "An error occurred while disabling scheduled task to backup recovery password. Error message: $($_.Exception.Message)" -Severity 3 + } + } + } + catch + { + Write-LogEntry -Value "An error occurred while reading 'BitLockerEscrowResults' registry value. Error message: $($_.Exception.Message)" -Severity 3 + } + } + } + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Enable-DNSOverHTTPS.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Enable-DNSOverHTTPS.ps1 new file mode 100644 index 0000000..ca89167 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Enable-DNSOverHTTPS.ps1 @@ -0,0 +1,271 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Enable DNS-over-HTTPS (DoH) if device is not domain-joined + + .DESCRIPTION + Enable DNS-over-HTTPS (DoH) if device is not domain-joined + + It enables the Cloudflare DNS Servers, even if DoH is not working yet. + + IPv6 Support is optional. + + .PARAMETER IPv6 + Enable IPv6 Support, IPv6 Servers will be added to the server list + + .EXAMPLE + PS C:\> .\Enable-DNSOverHTTPS.ps1 + + Enable DNS-over-HTTPS (DoH) if device is not domain-joined for IPv4 only + + .EXAMPLE + PS C:\> .\Enable-DNSOverHTTPS.ps1 -IPv6 + + Enable DNS-over-HTTPS (DoH) if device is not domain-joined for IPv4 and IPv6 + + .NOTES + Only the Insider Build of Windows 10 supports DoH! + But we configure it anyway! + + The Cloudflare servers are used for regular DNS resolution and as soon as DoH is supported, + we can configure and use it anyway. + + A future version of this script might support additional parameters, like DohFlags + + You can also change the servers below to any service you like, e.g. Google DNS or Quad9 from IBM. + + The Bool as return was requested by a customer, and the exit code (0 or 1) is implemented for our bootstrap setup + + .LINK + https://1.1.1.1/dns/ + + .LINK + https://techcommunity.microsoft.com/t5/networking-blog/windows-insiders-can-now-test-dns-over-https/ba-p/1381282 +#> +[CmdletBinding(ConfirmImpact = 'None')] +[OutputType([bool])] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('IP6', '6')] + [switch] + $IPv6 +) + +begin +{ + #region Defaults + $SCT = 'SilentlyContinue' + $STP = 'Stop' + $CNT = 'Continue' + + # Save the infos from the switches + if (($PSCmdlet.MyInvocation.BoundParameters['Verbose']).IsPresent) + { + $IsVerbose = $true + } + else + { + $IsVerbose = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['Debug']).IsPresent) + { + $IsDebug = $true + } + else + { + $IsDebug = $false + } + + if (($PSCmdlet.MyInvocation.BoundParameters['WhatIf']).IsPresent) + { + $IsWhatIf = $true + } + else + { + $IsWhatIf = $false + } + #endregion Defaults + + #region ServerAddresses + # Create an Empty Object + $ServerAddresses = @() + + # IPv4 DNS Servers to use + $ServerAddressesIPv4 = @( + '1.1.1.1' + '1.0.0.1' + ) + + # Add the IPv4 Servers to the Object + $ServerAddresses += $ServerAddressesIPv4 + + if ((($PSCmdlet.MyInvocation.BoundParameters['IPv6']).IsPresent) -eq $true) + { + Write-Verbose -Message 'IPv6 Servers will be added to the serverlist' + # IPv6 DNS Servers to use + $ServerAddressesIPv6 = @( + '2606:4700:4700::1111' + '2606:4700:4700::1001' + ) + + # Add the IPv6 Servers to the Object + $ServerAddresses += $ServerAddressesIPv6 + } + #endregion ServerAddresses +} + +process +{ + #region DoH + # Enable DNS-over-HTTPS for IPv4 if device is not domain-joined + $paramGetCimInstance = @{ + ClassName = 'CIM_ComputerSystem' + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $STP + } + if (((Get-CimInstance @paramGetCimInstance).PartOfDomain) -eq $false) + { + try + { + # Temporarily key + $paramNewItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\Dnscache\Parameters' + Name = 'EnableAutoDoh' + Value = 2 + PropertyType = 'DWord' + Force = $true + WhatIf = $IsWhatIf + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $CNT + } + $null = (New-ItemProperty @paramNewItemProperty) + + $paramGetNetAdapter = @{ + Verbose = $IsVerbose + Debug = $IsDebug + Physical = $true + ErrorAction = $SCT + } + $MACAddress = ((Get-NetAdapter @paramGetNetAdapter).MacAddress) + + $paramGetNetIPConfiguration = @{ + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $SCT + } + $IpConfig = (Get-NetIPConfiguration @paramGetNetIPConfiguration | Where-Object -FilterScript { + $MACAddress -eq $_.NetAdapter.MacAddress + }) + + $paramSetDnsClientServerAddress = @{ + ServerAddresses = $ServerAddresses + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $CNT + } + $null = ($IpConfig | Set-DnsClientServerAddress @paramSetDnsClientServerAddress) + + $paramClearDnsClientCache = @{ + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $SCT + } + $null = (Clear-DnsClientCache @paramClearDnsClientCache) + + $paramRegisterDnsClient = @{ + Verbose = $IsVerbose + Debug = $IsDebug + ErrorAction = $SCT + } + $null = (Register-DnsClient @paramRegisterDnsClient) + } + catch + { + # Get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $CNT + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + } + } + else + { + $paramWriteError = @{ + Message = 'Sorry, this computer seems to be part of a Active Directory domain!' + Exception = 'Active Directory Domain Members are not supported' + Category = 'NotEnabled' + TargetObject = $env:COMPUTERNAME + ErrorAction = $CNT + } + Write-Error @paramWriteError + + # Return the Bool + Write-Output -InputObject $false + + # Unclean exit + exit 1 + } + #endregion DoH +} + +end +{ + # Return the Bool + Write-Output -InputObject $true + + # Clean exit + exit 0 +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/EnhanceIntuneAgentLogging.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/EnhanceIntuneAgentLogging.ps1 new file mode 100644 index 0000000..440f865 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/EnhanceIntuneAgentLogging.ps1 @@ -0,0 +1,111 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Configure and enhance Endpoint Manager (Intune) Agent logging + + .DESCRIPTION + Configure and enhance Endpoint Manager (Intune) Agent logging + + .NOTES + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Configure and enhance Endpont Manager (Intune) Agent logging' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region Variables + # Cleanup + $logMaxSize = $null + + # Size in MB + $logMaxSize = 4 + + # Logic From MB to Bytes + $logMaxSize = ($logMaxSize * 1024 * 1024) + + # Define log files to keep + $logMaxHistory = 4 + + # Main Registry Path + $regKeyFullPath = 'HKLM:\SOFTWARE\Microsoft\IntuneWindowsAgent\Logging' + #endregion Variables +} + +process +{ + # Create the registry key path for the Endpont Manager (Intune) agent + $paramNewItem = @{ + Path = $regKeyFullPath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Set value to define new size instead of the default 2 MB + $paramSetItemProperty = @{ + Path = $regKeyFullPath + Name = 'LogMaxSize' + Value = $logMaxSize + Type = 'String' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + + # Set value to define new amount of logfiles to keep + $paramSetItemProperty = @{ + Path = $regKeyFullPath + Name = 'LogMaxHistory' + Value = $logMaxHistory + Type = 'String' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Get-AadJoinInformation.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Get-AadJoinInformation.ps1 new file mode 100644 index 0000000..181dec8 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Get-AadJoinInformation.ps1 @@ -0,0 +1,146 @@ +#requires -Version 2.0 + +<# + .SYNOPSIS + Get information from the local computer such as Azure AD join status, tenant Id, device id + + .DESCRIPTION + Get information from the local computer such as Azure AD join status, tenant Id, device id and such. Similar information as dsregcmd /status + + .EXAMPLE + .\Get-AadJoinInformation.ps1 + + .NOTES + Version 1.0.1 + + Based on Get-AadJoinInformation.ps1 1.0 from Mattias Fors (DeployWindows.com) +#> +[CmdletBinding(ConfirmImpact = 'None')] +[OutputType([int])] +param () + +begin +{ + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + $null = (Add-Type -TypeDefinition @' +using System; +using System.Collections.Generic; +using System.Text; +using System.Runtime.InteropServices; + +public class NetAPI32{ +public enum DSREG_JOIN_TYPE { +DSREG_UNKNOWN_JOIN, +DSREG_DEVICE_JOIN, +DSREG_WORKPLACE_JOIN +} + +[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] +public struct DSREG_USER_INFO { +[MarshalAs(UnmanagedType.LPWStr)] public string UserEmail; +[MarshalAs(UnmanagedType.LPWStr)] public string UserKeyId; +[MarshalAs(UnmanagedType.LPWStr)] public string UserKeyName; +} + +[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] +public struct CERT_CONTEX { +public uint dwCertEncodingType; +public byte pbCertEncoded; +public uint cbCertEncoded; +public IntPtr pCertInfo; +public IntPtr hCertStore; +} + +[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)] +public struct DSREG_JOIN_INFO +{ +public int joinType; +public IntPtr pJoinCertificate; +[MarshalAs(UnmanagedType.LPWStr)] public string DeviceId; +[MarshalAs(UnmanagedType.LPWStr)] public string IdpDomain; +[MarshalAs(UnmanagedType.LPWStr)] public string TenantId; +[MarshalAs(UnmanagedType.LPWStr)] public string JoinUserEmail; +[MarshalAs(UnmanagedType.LPWStr)] public string TenantDisplayName; +[MarshalAs(UnmanagedType.LPWStr)] public string MdmEnrollmentUrl; +[MarshalAs(UnmanagedType.LPWStr)] public string MdmTermsOfUseUrl; +[MarshalAs(UnmanagedType.LPWStr)] public string MdmComplianceUrl; +[MarshalAs(UnmanagedType.LPWStr)] public string UserSettingSyncUrl; +public IntPtr pUserInfo; +} + +[DllImport("netapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)] +public static extern void NetFreeAadJoinInformation( +IntPtr pJoinInfo); + +[DllImport("netapi32.dll", CharSet=CharSet.Unicode, SetLastError=true)] +public static extern int NetGetAadJoinInformation( +string pcszTenantId, +out IntPtr ppJoinInfo); +} +'@ -ErrorAction $SCT) + + $pcszTenantId = $null + $ptrJoinInfo = [IntPtr]::Zero +} + +process +{ + # https://docs.microsoft.com/en-us/windows/win32/api/lmjoin/nf-lmjoin-netgetaadjoininformation + [NetAPI32]::NetFreeAadJoinInformation([IntPtr]::Zero) + $retValue = [NetAPI32]::NetGetAadJoinInformation($pcszTenantId, [ref]$ptrJoinInfo) + + # https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/18d8fbe8-a967-4f1c-ae50-99ca8e491d2d + if ($retValue -eq 0) + { + # https://support.microsoft.com/en-us/help/2909958/exceptions-in-windows-powershell-other-dynamic-languages-and-dynamical + + $paramNewObject = @{ + TypeName = 'NetAPI32+DSREG_JOIN_INFO' + } + $ptrJoinInfoObject = (New-Object @paramNewObject) + $joinInfo = ([Runtime.InteropServices.Marshal]::PtrToStructure($ptrJoinInfo, [type]$ptrJoinInfoObject.GetType()) | Select-Object -ExpandProperty joinType) + + switch ($joinInfo) + { + ([NetAPI32+DSREG_JOIN_TYPE]::DSREG_DEVICE_JOIN.value__) + { + Write-Verbose -Message 'Device is joined' + + [int]$JoinType = 1 + } + ([NetAPI32+DSREG_JOIN_TYPE]::DSREG_UNKNOWN_JOIN.value__) + { + Write-Verbose -Message 'Device is not joined, or unknown type' + [int]$JoinType = 0 + } + ([NetAPI32+DSREG_JOIN_TYPE]::DSREG_WORKPLACE_JOIN.value__) + { + Write-Verbose -Message 'Device workplace joined' + + [int]$JoinType = 2 + } + } + } + else + { + Write-Verbose -Message 'Not Azure Joined' + + [int]$JoinType = 0 + } +} + +end +{ + $JoinType + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-AllMissingMicrosoftUpdates.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-AllMissingMicrosoftUpdates.ps1 new file mode 100644 index 0000000..ac6e3ae --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-AllMissingMicrosoftUpdates.ps1 @@ -0,0 +1,243 @@ +#requires -Version 3.0 -Modules PSWindowsUpdate -RunAsAdministrator + +<# + .SYNOPSIS + Install all missing Microsoft updated + + .DESCRIPTION + Install all missing Microsoft updated using the PSWindowsUpdate module + + .NOTES + Version 1.0.3 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Install all missing Microsoft updated' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + #region HelperFunctions + function Test-GetWUServiceManager + { + <# + .SYNOPSIS + Check if WUServiceManager is configured + + .DESCRIPTION + Check if WUServiceManager is configured + + .EXAMPLE + PS C:\> Test-GetWUServiceManager + + .NOTES + Additional information about the function. + #> + [CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] + [OutputType([bool])] + param () + + begin + { + #region Defaults + $SCT = 'SilentlyContinue' + $ServiceID = '7971f918-a847-4430-9279-4a52d1efe18d' + #endregion Defaults + } + + process + { + $paramGetWUServiceManager = @{ + ComputerName = $env:COMPUTERNAME + ServiceID = $ServiceID + ErrorAction = $SCT + } + $WUServiceManager = (Get-WUServiceManager @paramGetWUServiceManager) + + if (-not ($WUServiceManager)) + { + $paramAddWUServiceManager = @{ + ComputerName = $env:COMPUTERNAME + ServiceID = $ServiceID + Confirm = $false + ErrorAction = $SCT + } + $null = (Add-WUServiceManager @paramAddWUServiceManager) + + return $false + } + else + { + return $true + } + } + } + + function Invoke-GetWindowsUpdate + { + <# + .SYNOPSIS + Wrapper for Get-WindowsUpdate + + .DESCRIPTION + Wrapper for Get-WindowsUpdate + + .EXAMPLE + PS C:\> Invoke-GetWindowsUpdate + + .NOTES + Additional information about the function. + #> + [CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] + param () + + begin + { + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + $paramGetWindowsUpdate = @{ + ComputerName = $env:COMPUTERNAME + MicrosoftUpdate = $true + Install = $true + ForceInstall = $true + IgnoreUserInput = $true + AcceptAll = $true + AutoReboot = $false + IgnoreReboot = $true + Criteria = "IsHidden=0 and IsInstalled=0 and Type='Software'" + WhatIf = $false + Verbose = $true + ErrorAction = $SCT + WarningAction = $SCT + } + } + + process + { + $null = (Get-WindowsUpdate @paramGetWindowsUpdate) + } + } + #endregion HelperFunctions +} + +process +{ + if (Test-GetWUServiceManager -ErrorAction $SCT) + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + $null = (Invoke-GetWindowsUpdate -ErrorAction $SCT) + } + else + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry to fix it + $null = (Test-GetWUServiceManager -ErrorAction $SCT) + + $Retry = $true + } + + if ($Retry -eq $true) + { + if (Test-GetWUServiceManager -ErrorAction $SCT) + { + # Stop Search - Gain performance + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (Invoke-GetWindowsUpdate -ErrorAction $SCT) + } + else + { + Write-Warning -Message 'Unable to apply the latest Microsoft updates, please check and apply them manually!' -WarningAction Stop + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-AutoPilotRelated.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-AutoPilotRelated.ps1 new file mode 100644 index 0000000..4ca5afd --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-AutoPilotRelated.ps1 @@ -0,0 +1,186 @@ +#requires -Version 2.0 -Modules PackageManagement, PowerShellGet -RunAsAdministrator + +<# + .SYNOPSIS + Check and install all prerequisites and dependencies, if they are needed + + .DESCRIPTION + Check and install all prerequisites and dependencies, if they are needed + + .EXAMPLE + PS C:\> .\Install-AutoPilotRelated.ps1 + + # Check and install all prerequisites and dependencies, if they are needed + + .NOTES + Version 1.0.1 + + Additional information about the file. +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + #region Global + $IGN = 'Ignore' + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + $paramFindPackageProvider = @{ + Name = 'NuGet' + ForceBootstrap = $true + IncludeDependencies = $true + Force = $true + ErrorAction = $SCT + } + + $paramInstallModule = @{ + Force = $true + Scope = 'AllUsers' + AllowClobber = $true + SkipPublisherCheck = $true + Confirm = $false + ErrorAction = $SCT + } + + $paramSetPSRepository = @{ + Name = 'PSGallery' + InstallationPolicy = 'Trusted' + ErrorAction = $SCT + } + + $paramInstallScript = @{ + Name = 'Get-WindowsAutoPilotInfo' + Scope = 'AllUsers' + Force = $true + Confirm = $false + ErrorAction = $SCT + } + #endregion Global + + #region Cleanup + $NuGetProvider = $null + $WindowsAutopilotIntuneModule = $null + $AzureADModule = $null + $ScriptInfo = $null + #endregion Cleanup + + #region GatherInfo + $paramGetPackageProvider = @{ + Name = 'NuGet' + ErrorAction = $IGN + } + $NuGetProvider = (Get-PackageProvider @paramGetPackageProvider) + + $paramImportModule = @{ + NoClobber = $true + DisableNameChecking = $true + PassThru = $true + ErrorAction = $IGN + } + + # Get the module info + $WindowsAutopilotIntuneModule = (Import-Module -Name WindowsAutopilotIntune @paramImportModule) + $AzureADModule = (Import-Module -Name AzureAD @paramImportModule) + + # Get the repository info + $PSRepositoryInfo = (Get-PSRepository -Name PSGallery -ErrorAction $SCT) + #endregion GatherInfo + + #region + $paramGetInstalledScript = @{ + Name = 'Get-WindowsAutoPilotInfo' + ErrorAction = $SCT + } + $ScriptInfo = (Get-InstalledScript @paramGetInstalledScript) + #endregion +} + +process +{ + #region PackageProvider + # Get the NuGet PackageProvider for the PowerShell Gallery, if needed + if (-not $NuGetProvider) + { + $null = (Find-PackageProvider @paramFindPackageProvider) + } + #endregion PackageProvider + + #region PSRepository + if (($PSRepositoryInfo | Select-Object -ExpandProperty InstallationPolicy) -ne $true) + { + $null = (Set-PSRepository @paramSetPSRepository) + } + #endregion PSRepository + + #region ModuleHandler + # Get Azure AD module, if needed + if (-not $AzureADModule) + { + $null = (Install-Module -Name AzureAD @paramInstallModule) + } + + # Get WindowsAutopilotIntune module, if needed + if (-not $WindowsAutopilotIntuneModule) + { + $null = (Install-Module -Name WindowsAutopilotIntune @paramInstallModule) + } + #endregion ModuleHandler + + #region ScriptHandler + # Install the Helper script from the Gallery + if (-not $ScriptInfo) + { + $null = (Install-Script @paramInstallScript) + } + #endregion ScriptHandler +} + +end +{ + #region Cleanup + $NuGetProvider = $null + $WindowsAutopilotIntuneModule = $null + $AzureADModule = $null + $ScriptInfo = $null + #endregion Cleanup + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-Choco.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-Choco.ps1 new file mode 100644 index 0000000..9636ab7 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-Choco.ps1 @@ -0,0 +1,232 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install the chocolatey default base packages + + .DESCRIPTION + Download and install the chocolatey default base packages + + .NOTES + These are the chocolatey default packages, that we want to have on all new systems + + Changelog: + 1.3.7: Removed vscode-powershell + 1.3.6: Add 'FiraCode-ttf' (Requested) and removed 'notepadplusplus' (Replaced by VSCode) + 1.3.4: Reformatted + 1.3.3: Removed Chromium Edge (Now part of Windows 10) + + Version 1.3.7 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install the chocolatey default base packages' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + if (-not $env:ChocolateyInstall) + { + $env:ChocolateyInstall = 'C:\ProgramData\chocolatey' + } + #endregion + + #region ChocoCacheLocation + $ChocoCacheLocation = "$env:HOMEDRIVE\temp\choco\" + $paramTestPath = @{ + Path = $ChocoCacheLocation + ErrorAction = $SCT + WarningAction = '-' + Filter = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $ChocoCacheLocation + ItemType = 'directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = '-' + Value = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion ChocoCacheLocation + + #region + $paramGetCommand = @{ + Name = 'Update-SessionEnvironment' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramTestPath = @{ + Path = "$env:ChocolateyInstall\bin\refreshenv.cmd" + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $null = (Update-SessionEnvironment -WarningAction $SCT -ErrorAction $SCT) + } + elseif (Test-Path @paramTestPath) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + 'BGInfo' + 'chocolatey-core.extension' + 'chocolatey-dotnetfx.extension' + 'chocolatey-misc-helpers.extension' + 'chocolatey-windowsupdate.extension' + 'chocolatey-font-helpers.extension' + 'chocolatey-vscode.extension' + 'chocolatey-vscode' + 'FiraCode' + 'FiraCode-ttf' + 'Cascadia' + 'CascadiaMono' + 'CascadiaMonoPL' + 'microsoft-edge' + 'nuget.commandline' + 'nxlog' + 'powershell-core' + 'vscode' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (& "$env:ChocolateyInstall\bin\choco.exe" install $ChocoPackage --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1') + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" install $ChocoPackage --ignore-checksums --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1') + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages.ps1 new file mode 100644 index 0000000..1d8b383 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages.ps1 @@ -0,0 +1,211 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install the chocolatey default base packages + + .DESCRIPTION + Download and install the chocolatey default base packages + + .NOTES + These are the chocolatey default packages, that we want to have on all new systems + + Changelog: + 1.4.0: Switched from 'Install' to 'upgrade' as Choco command (More flexible and robust) + 1.3.9: Add Cache Location to all Choco commands and makle sure it exist + 1.3.7: Removed vscode-powershell + 1.3.6: Add 'FiraCode-ttf' (Requested) and removed 'notepadplusplus' (Replaced by VSCode) + 1.3.4: Reformatted + 1.3.3: Removed Chromium Edge (Now part of Windows 10) + + Version 1.4.0 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install the chocolatey default base packages' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + if (-not $env:ChocolateyInstall) + { + $env:ChocolateyInstall = 'C:\ProgramData\chocolatey' + } + #endregion + + #region + $paramGetCommand = @{ + Name = 'Update-SessionEnvironment' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramTestPath = @{ + Path = "$env:ChocolateyInstall\bin\refreshenv.cmd" + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $null = (Update-SessionEnvironment -WarningAction $SCT -ErrorAction $SCT) + } + elseif (Test-Path @paramTestPath) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + 'BGInfo' + 'chocolatey-core.extension' + 'chocolatey-dotnetfx.extension' + 'chocolatey-misc-helpers.extension' + 'chocolatey-windowsupdate.extension' + 'chocolatey-font-helpers.extension' + 'chocolatey-vscode.extension' + 'chocolatey-vscode' + 'FiraCode' + 'FiraCode-ttf' + 'Cascadia' + 'CascadiaMono' + 'CascadiaMonoPL' + 'microsoft-edge' + 'nuget.commandline' + 'nxlog' + 'powershell-core' + 'vscode' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (& "$env:ChocolateyInstall\bin\choco.exe" install $ChocoPackage --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1') + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" install $ChocoPackage --ignore-checksums --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1') + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_User.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_User.ps1 new file mode 100644 index 0000000..df90dc9 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_User.ps1 @@ -0,0 +1,221 @@ +#requires -Version 3.0 + +<# + .SYNOPSIS + Download and install the chocolatey default packages for the user context + + .DESCRIPTION + Download and install the chocolatey default packages for the user context + + .NOTES + All chocolatey in this file will be installed into: C:\Users\\AppData\Local\chocoportable + + Changelog: + 1.0.0: Switched from 'Install' to 'upgrade' as Choco command (More flexible and robust) + 0.0.10: Add Cache Location to all Choco commands and make sure it exist + 0.0.9: Initial Test version + + Version 1.0.0 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs + + .LINK + https://chocolatey.org/docs/installation#non-administrative-install +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install the chocolatey default packages for Workstations' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region SetExecutionPolicy + $null = (Set-ExecutionPolicy -Scope CurrentUser Bypass -Force -ErrorAction $SCT) + $null = (Set-ExecutionPolicy -Scope Process Bypass -Force -ErrorAction $SCT) + #endregion SetExecutionPolicy + + #region ChocolateyInstallPath + # Use the User Profile + $env:ChocolateyInstall = ($env:LOCALAPPDATA + '\chocoportable') + #endregion ChocolateyInstallPath + + #region ChocoCacheLocation + $ChocoCacheLocation = "$env:HOMEDRIVE\temp\choco\" + $paramTestPath = @{ + Path = $ChocoCacheLocation + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $ChocoCacheLocation + ItemType = 'directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion ChocoCacheLocation + + #region + $paramGetCommand = @{ + Name = 'Update-SessionEnvironment' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramTestPath = @{ + Path = "$env:ChocolateyInstall\bin\refreshenv.cmd" + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramUpdateSessionEnvironment = @{ + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Update-SessionEnvironment @paramUpdateSessionEnvironment) + } + elseif (Test-Path @paramTestPath) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + '1password' + 'op' + 'auto-dark-mode' + 'microsoft-windows-terminal' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # This should install everything into the User Profile - The first installation will take longer then normal + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --allowemptychecksum --ignore-checksums --ignore-dependencies --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=0' --cacheLocation=$ChocoCacheLocation) + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --allowemptychecksum --ignore-checksums --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_Workstation.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_Workstation.ps1 new file mode 100644 index 0000000..008bc29 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_Workstation.ps1 @@ -0,0 +1,250 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install the chocolatey default packages for Workstations + + .DESCRIPTION + Download and install the chocolatey default packages for Workstations + + .NOTES + These are the chocolatey default packages, that we want to have on all new systems + + Changelog: + 1.2.0: Switched from 'Install' to 'upgrade' as Choco command (More flexible and robust) + 1.1.11: Add Cache Location to all Choco commands and makle sure it exist + 1.1.10: Add Git Fork Client + 1.1.9: Add 'choco-cleaner' + 1.1.8: Removed Python (Now a DEV package) + 1.1.7: Fix some issues and add some 'Install' packages + 1.1.6: Reformatted + 1.1.5: Removed "Firefox", "Chrome", and "graphviz" - All moved to the Developer package selection + + Version 1.2.0 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install the chocolatey default packages for Workstations' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + if (-not $env:ChocolateyInstall) + { + $env:ChocolateyInstall = 'C:\ProgramData\chocolatey' + } + #endregion + + #region ChocoCacheLocation + $ChocoCacheLocation = "$env:HOMEDRIVE\temp\choco\" + $paramTestPath = @{ + Path = $ChocoCacheLocation + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $ChocoCacheLocation + ItemType = 'directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion ChocoCacheLocation + + #region + $paramGetCommand = @{ + Name = 'Update-SessionEnvironment' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramTestPath = @{ + Path = "$env:ChocolateyInstall\bin\refreshenv.cmd" + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramUpdateSessionEnvironment = @{ + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Update-SessionEnvironment @paramUpdateSessionEnvironment) + } + elseif (Test-Path @paramTestPath) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + '1password' # Used to get dependencies + 'op' # Used to get dependencies + 'auto-dark-mode' # Used to get dependencies + 'microsoft-windows-terminal' # Used to get dependencies + 'choco-cleaner' + 'cyberduck.install' + 'chocolateygui' + 'curl' + 'displaylink' + 'git.install' + 'git-credential-manager-for-windows' + 'git-credential-winstore' + 'keepass.install' + 'keepassxc' + 'keepass-plugin-1p2kp' + 'keepass-plugin-qrcodegen' + 'keepass-plugin-rdp' + 'keepass-plugin-keeotp' + 'keepass-plugin-keechallenge' + 'makemeadmin' + 'marktext.install' + 'paint.net' + 'powertoys' + 'putty.install' + 'vlc' + 'winscp.install' + 'yubikey-manager' + 'yubikey-personalization-tool' + 'yubikey-piv-manager' + 'yubico-authenticator' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --allowemptychecksum --ignore-checksums --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_design.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_design.ps1 new file mode 100644 index 0000000..01b4869 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_design.ps1 @@ -0,0 +1,240 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install the chocolatey default packages for Workstations + + .DESCRIPTION + Download and install the chocolatey default packages for Workstations + + .NOTES + These are the chocolatey default packages, that we want to have on all new systems + + Changelog: + 1.2.0: Switched from 'Install' to 'upgrade' as Choco command (More flexible and robust) + 1.1.13: Add Cache Location to all Choco commands and make sure it exist + + Version 1.2.0 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install the chocolatey default packages for Workstations' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + if (-not $env:ChocolateyInstall) + { + $env:ChocolateyInstall = 'C:\ProgramData\chocolatey' + } + #endregion + + #region ChocoCacheLocation + $ChocoCacheLocation = "$env:HOMEDRIVE\temp\choco\" + $paramTestPath = @{ + Path = $ChocoCacheLocation + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $ChocoCacheLocation + ItemType = 'directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion ChocoCacheLocation + + #region + $paramGetCommand = @{ + Name = 'Update-SessionEnvironment' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramTestPath = @{ + Path = "$env:ChocolateyInstall\bin\refreshenv.cmd" + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $null = (Update-SessionEnvironment -WarningAction $SCT -ErrorAction $SCT) + } + elseif (Test-Path @paramTestPath) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + 'Scribus' + 'InkScape' + 'gimp' + 'google-web-designer' + 'bluefish' + 'komodo-edit' + 'bluegriffon' + 'aptana-studio' + 'pngoptimizer' + 'pngoptimizer.commandline' + 'OptiPNG' + 'exiftool' + 'exiftoolgui' + 'IrfanView' + 'irfanview-shellextension' + 'irfanviewplugins' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --allowemptychecksum --ignore-checksums --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_dev.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_dev.ps1 new file mode 100644 index 0000000..482411f --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_dev.ps1 @@ -0,0 +1,259 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install chocolatey default packages for developer Workstations + + .DESCRIPTION + Download and install chocolatey default packages for developer Workstations + + .NOTES + Some of the stiff is not for regular workstations + + Changelog: + 1.1.0: Switched from 'Install' to 'upgrade' as Choco command (More flexible and robust) + 1.0.13: Add Cache Location to all Choco commands and make sure it exist + 1.0.12: Removed 'choco-cleaner' (Now part of the Default Workstation install) + 1.0.11: Python is now part of this package + 1.0.10: Removed some packages from the Dev Default + 1.0.9: Reformatted + 1.0.8: Added 'microsoft-edge-insider' and 'microsoft-edge-insider-dev' + 1.0.7: Added "Firefox", "Chrome", and "graphviz" - Removed from the Default Workstation packages + + Version 1.1.0 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install chocolatey default packages for developer Workstations' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + if (-not $env:ChocolateyInstall) + { + $env:ChocolateyInstall = 'C:\ProgramData\chocolatey' + } + #endregion + + #region ChocoCacheLocation + $ChocoCacheLocation = "$env:HOMEDRIVE\temp\choco\" + $paramTestPath = @{ + Path = $ChocoCacheLocation + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $ChocoCacheLocation + ItemType = 'directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion ChocoCacheLocation + + #region + $paramGetCommand = @{ + Name = 'Update-SessionEnvironment' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramTestPath = @{ + Path = "$env:ChocolateyInstall\bin\refreshenv.cmd" + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $null = (Update-SessionEnvironment -WarningAction $SCT -ErrorAction $SCT) + } + elseif (Test-Path @paramTestPath) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + 'GoogleChrome' + 'git-fork' + 'graphviz' + 'microsoft-edge-insider' + 'gh' + 'github-desktop' + 'Firefox' + 'winmerge' + 'electron' + 'cmake' + 'regextester' + 'powershell-preview' + 'brave' + 'sysinternals' + 'chromium' + 'GoogleChrome' + 'yarn' + 'nodejs' + 'NugetPackageExplorer' + 'NuGet.ContextMenu' + 'Paket.PowerShell' + 'python3' + 'postman' + 'fiddler' + 'lockhunter' + 'dos2unix' + 'markpad' + 'dotnetcore-sdk' + 'dotnetcore-sdk -version 2.2.0' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --allowemptychecksum --ignore-checksums --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_dotnet.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_dotnet.ps1 new file mode 100644 index 0000000..284d61c --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_dotnet.ps1 @@ -0,0 +1,233 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install some Microsoft .NET Runtimes + + .DESCRIPTION + Download and install some Microsoft .NET and Core Runtimes as chocolatey default packages + + .NOTES + Added dotNET Core and Core SDK to the latest version of this script. + We also added dotNET Core SDK version 2.2 for some legacy stuff + + Changelog: + 1.2.0: Switched from 'Install' to 'upgrade' as Choco command (More flexible and robust) + 1.1.7: Add Cache Location to all Choco commands and make sure it exist + 1.1.6: Reformatted + 1.1.5: Add 'dotnetcore3-desktop-runtime' (Required for PowerToys Package) + + Version 1.2.0 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install some Microsoft .NET Runtimes' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + if (-not $env:ChocolateyInstall) + { + $env:ChocolateyInstall = 'C:\ProgramData\chocolatey' + } + #endregion + + #region ChocoCacheLocation + $ChocoCacheLocation = "$env:HOMEDRIVE\temp\choco\" + $paramTestPath = @{ + Path = $ChocoCacheLocation + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $ChocoCacheLocation + ItemType = 'directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion ChocoCacheLocation + + #region + $paramGetCommand = @{ + Name = 'Update-SessionEnvironment' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramTestPath = @{ + Path = "$env:ChocolateyInstall\bin\refreshenv.cmd" + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $null = (Update-SessionEnvironment -WarningAction $SCT -ErrorAction $SCT) + } + elseif (Test-Path @paramTestPath) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + 'DotNet3.5' + 'DotNet4.5' + 'dotnet4.7' + 'dotnetfx' + 'dotnetcore' + 'dotnetcore3-desktop-runtime' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --allowemptychecksum --ignore-checksums --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_vcredist.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_vcredist.ps1 new file mode 100644 index 0000000..8c9ba7f --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-ChocoPackages_vcredist.ps1 @@ -0,0 +1,222 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install some legacy Microsoft Visual C++ Redistributable + + .DESCRIPTION + Download and install some legacy Microsoft Visual C++ Redistributable as chocolatey default packages + + .NOTES + We install the following: 2013, 2015, 2017, and vcredist140 + + Changelog: + 1.1.0: Switched from 'Install' to 'upgrade' as Choco command (More flexible and robust) + 1.0.9: Add Cache Location to all Choco commands and make sure it exist + + Version 1.1.0 + + .LINK + http://enatec.io + + .LINK + https://chocolatey.org/docs +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install some legacy Microsoft Visual C++ Redistributable' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + #region + if (-not $env:ChocolateyInstall) + { + $env:ChocolateyInstall = 'C:\ProgramData\chocolatey' + } + #endregion + + #region ChocoCacheLocation + $ChocoCacheLocation = "$env:HOMEDRIVE\temp\choco\" + $paramTestPath = @{ + Path = $ChocoCacheLocation + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $ChocoCacheLocation + ItemType = 'directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + #endregion ChocoCacheLocation + + #region + if (Get-Command -Name Update-SessionEnvironment -WarningAction $SCT -ErrorAction $SCT) + { + $null = (Update-SessionEnvironment -WarningAction $SCT -ErrorAction $SCT) + } + elseif (Test-Path -Path "$env:ChocolateyInstall\bin\refreshenv.cmd" -WarningAction $SCT -ErrorAction $SCT) + { + $null = (& "$env:ChocolateyInstall\bin\refreshenv.cmd") + } + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + try + { + $null = ([Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor 3072) + } + catch + { + Write-Verbose -Message 'Unable to set PowerShell to use TLS 1.2.' + } + + # Use Windows built-in compression instead of downloading 7zip + $env:chocolateyUseWindowsCompression = 'true' + + $AllChocoPackages = @( + #'vcredist2005' + #'vcredist2008' + #'vcredist2010' + #'vcredist2012' + 'vcredist2013' + 'vcredist2015' + 'vcredist2017' + 'vcredist140' + ) + + # Initial Package Counter + $PackageCounter = 1 +} + +process +{ + foreach ($ChocoPackage in $AllChocoPackages) + { + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + Write-Verbose -Message ('Start the installation of ' + $ChocoPackage) + + if ($pscmdlet.ShouldProcess($ChocoPackage, 'Install')) + { + Write-Progress -Activity ('Installing ' + $ChocoPackage) -Status ('Package ' + $PackageCounter + ' of ' + $($AllChocoPackages.Count)) -PercentComplete (($PackageCounter / $AllChocoPackages.Count) * 100) + + try + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + } + catch + { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Retry with --ignore-checksums - A less secure option!!! + $null = (& "$env:ChocolateyInstall\bin\choco.exe" upgrade $ChocoPackage --allowemptychecksum --ignore-checksums --ignoredetectedreboot --no-progress --acceptlicense --limitoutput --no-progress --yes --force --params 'ALLUSERS=1' --cacheLocation=$ChocoCacheLocation) + # Some Packages (e.g. Sysmon) use the latest and greatest version, the checksum check will cause issues in this case! + } + } + + # Add Package Step + $PackageCounter++ + } + catch + { + Write-Warning -Message ('Installation of ' + $ChocoPackage + ' failed!') + + # Add Package Step + $PackageCounter++ + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-LatestTeamsClient.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-LatestTeamsClient.ps1 new file mode 100644 index 0000000..d3462b0 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-LatestTeamsClient.ps1 @@ -0,0 +1,220 @@ +#requires -Version 3.0 + +<# + .SYNOPSIS + Download and install latest version of Microsoft Teams + + .DESCRIPTION + Force the download and the installation latest version of Microsoft Teams for the used OS architecture + + .NOTES + Early testing release - Future releases might get some parameters + + Changelog: + 2.0.0: Changed back to the MSI installation + 1.0.4: Reformatted + 1.0.3: Removed the Firewall Rule creation (Now part of Invoke-TweakTeamsClientFirewall.ps1) + 1.0.2: Removed the WMI call to find OS architecture - Replaced with native .Net type System.IntPtr + 1.0.1: Use BitsTransfer instead of Invoke-WebRequest + 1.0.0: Initial Release + + Version 2.0.0 + + .LINK + http://enatec.io + + .LINK + https://docs.microsoft.com/en-us/microsoftteams/msi-deployment +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download and install latest version of the Microsoft Teams MSI package' + + # Default URL (Assume we use 64Bit) + [string]$Teams64BitUrl = 'https://teams.microsoft.com/downloads/desktopurl?env=production&plat=windows&arch=x64&managedInstaller=true&download=true' + + #region PossibleParameters + # Where to Store it + [string]$Target = ($env:Temp) + + # Install Switch + [string]$Arguments = 'OPTIONS="noAutoStart=true" ALLUSERS=1 /qn /norestart' + #endregion PossibleParameters + + #region Defaults + $SCT = 'SilentlyContinue' + $STP = 'Stop' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } +} + +process +{ + # Processor architecture will set the installer (64Bit is the default) + switch ([IntPtr]::Size) + { + 4 + { + Write-Warning -Message 'You have a 32-bit processor - This is no longer supported by enabling Technology!' -WarningAction Continue + + $Url = 'https://teams.microsoft.com/downloads/desktopurl?env=production&plat=windows&managedInstaller=true&download=true' + } + Default + { + Write-Verbose -Message 'Use the default: 64-bit processor' + + $Url = $Teams64BitUrl + } + } + + # Get the URL + $request = (Invoke-WebRequest -Uri $Url -MaximumRedirection 0 -ErrorAction $SCT) + + if ($request.StatusDescription -eq 'found') + { + # Get the full path of the downloaded installer + $paramSplitPath = @{ + Path = $request.Headers.Location + Leaf = $true + } + $Installer = ($Target + '\' + (Split-Path @paramSplitPath)) + + Write-Verbose -Message ('Downloading {0} to {1}' -f $request.Headers.Location, $Installer) + + # Use BitsTransfer to download the latest installer + $paramStartBitsTransfer = @{ + Source = $request.Headers.Location + Destination = $Installer + Priority = 'Foreground' + TransferPolicy = 'Always' + ErrorAction = $STP + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + } + else + { + Write-Verbose -Message ('Answer: {0}' -f $request.StatusDescription) + + Write-Error -Message 'Unable to download the Teams MSI Installer' -ErrorAction $STP + + # We are done + break + } + + # Install the Microsoft Teams client + $paramTestPath = @{ + Path = $Installer + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + Write-Verbose -Message 'Running installer Microsoft Teams' + + $paramStartProcess = @{ + FilePath = $Installer + ArgumentList = $Arguments + Wait = $true + PassThru = $true + ErrorAction = $STP + } + $InstallerProcess = (Start-Process @paramStartProcess) + + if (($InstallerProcess | Select-Object -ExpandProperty ExitCode) -eq 0) + { + Write-Verbose -Message 'Installed Microsoft Teams version' + } + else + { + Write-Warning -Message ('Installer exit code: {0}.' -f $InstallerProcess.ExitCode) + } + + Write-Verbose -Message ('Removing file: {0}' -f $Installer) + + $paramRemoveItem = @{ + Path = $Installer + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + else + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # We are done + break + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } + + if ($InstallerProcess.ExitCode) + { + exit($InstallerProcess.ExitCode) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-PowerShellModules_dev.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-PowerShellModules_dev.ps1 new file mode 100644 index 0000000..c03d277 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-PowerShellModules_dev.ps1 @@ -0,0 +1,164 @@ +#requires -Version 2.0 -RunAsAdministrator + +<# + .SYNOPSIS + Install some additional PowerShell Modules for Developers + + .DESCRIPTION + Install some additional PowerShell Modules for Developers from the PowerShell Gallery + + .NOTES + Version 1.0.5 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Install some additional developer related PowerShell Modules' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + + # Every System should have these Modules + $PowerShellModuleList = @( + 'ExchangeOnlineManagement' + 'ADAL.PS' + 'Az' + 'AzureAD' + 'AzureADPreview' + 'BuildHelpers' + 'ChangelogManagement' + 'Configuration' + 'CredentialManager' + 'ExchangeOnlineShell' + 'Exch-Rest' + 'EXOTools' + 'ImportExcel' + 'InvokeBuild' + 'Invoke-CommandAs' + 'Microsoft.Graph' + 'SharePointPnPPowerShellOnline' + 'Microsoft.Online.SharePoint.PowerShell' + 'MicrosoftGraphAPI' + 'MicrosoftGraphSecurity' + 'MicrosoftStaffHub' + 'ModuleBuild' + 'ModuleBuilder' + 'MSCloudLoginAssistant' + 'MSGraphAPI' + 'MSGraphIntuneManagement' + 'MSGraphTokenLifetimePolicy' + 'MSOLLicenseManagement' + 'MSOnline' + 'Office365GraphAPI' + 'OneDrive' + 'ORCA' + 'platyPS' + 'Plaster' + 'PlasterManifestDSL' + 'Pode' + 'Polaris' + 'PoshNotify' + 'powershell-yaml' + 'psake' + 'PSCodeHealth' + 'PScribo' + 'PSDepend' + 'PSModuleBuild' + 'PSModuleBuildHelper' + 'PSModuleDevelopment' + 'PSParseHTML' + 'PSPesterTest' + 'PSTeams' + ) +} + +process +{ + # Force the installation of the Modules listed above + $null = ($PowerShellModuleList | ForEach-Object -Process { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $paramInstallModule = @{ + Name = $_ + Scope = 'AllUsers' + Repository = 'PSGallery' + Force = $true + Confirm = $false + AllowClobber = $true + SkipPublisherCheck = $true + ErrorAction = $SCT + } + (Install-Module @paramInstallModule) + + Start-Sleep -Seconds 5 + }) + + # Refresh + $paramGetModule = @{ + ListAvailable = $true + Refresh = $true + ErrorAction = $SCT + } + $null = (Get-Module @paramGetModule) +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2020, Beyond Datacenter + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-PowerShellModules_required.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-PowerShellModules_required.ps1 new file mode 100644 index 0000000..d76f122 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-PowerShellModules_required.ps1 @@ -0,0 +1,117 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Install some mandatory PowerShell Modules + + .DESCRIPTION + Install some mandatory PowerShell Modules from the PowerShell Gallery + + .NOTES + Version 1.0.2 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Install some mandatory PowerShell Modules' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + # Every System should have these Modules + $PowerShellModuleList = @( + 'PoShKeePass' + 'Pester' + 'PackageManagement' + 'PowerShellGet' + 'PSScriptAnalyzer' + 'posh-git' + 'PSWindowsUpdate' + 'BurntToast' + ) +} + +process +{ + # Force the installation of the Modules listed above + $null = ($PowerShellModuleList | ForEach-Object -Process { + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object -FilterScript { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + $paramInstallModule = @{ + Name = $_ + Scope = 'AllUsers' + Repository = 'PSGallery' + Force = $true + Confirm = $false + AllowClobber = $true + SkipPublisherCheck = $true + ErrorAction = $SCT + } + $null = (Install-Module @paramInstallModule) + + Start-Sleep -Seconds 5 + }) + + # Refresh + $null = (Get-Module -ListAvailable -Refresh -ErrorAction $SCT) +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-SkypeOnlinePowerShellModule.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-SkypeOnlinePowerShellModule.ps1 new file mode 100644 index 0000000..eea4687 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-SkypeOnlinePowerShellModule.ps1 @@ -0,0 +1,150 @@ +#requires -Version 3.0 -Modules BitsTransfer -RunAsAdministrator + +<# + .SYNOPSIS + Download and install the Skype for Business Online PowerShell Module + + .DESCRIPTION + Download and install the Skype for Business Online PowerShell Module + + .NOTES + It may be necessary to set up Windows Remote Management (WinRM)! + + If the connect to Skype for Business Online and/or Microsoft Teams requires to, + please execute the following command(s) in an administrative (elevated) command prompt/PowerShell: + + winrm quickconfig + + And optionally this (for legacy authentication fallback support): + winrm set winrm/config/client/auth@{Basic="true"} + + Changelog: + 1.0.0: Initial Release + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Warning -Message 'This module is no longer supported and recommended!' + Write-Warning -Message 'Please use the Microsoft Teams Module instead!!!' + + exit 1 + + Write-Output -InputObject 'Download and install the Skype for Business Online PowerShell Module' + + # Default URL + [string]$SkypeOnlinePowerShellUrl = 'https://download.microsoft.com/download/2/0/5/2050B39B-4DA5-48E0-B768-583533B42C3B/SkypeOnlinePowerShell.exe' + + #region PossibleParameters + # Where to Store it + [string]$Target = ($env:Temp) + + # File Name + [string]$TargetName = 'SkypeOnlinePowerShell.exe' + + # Install Switch + [string]$Arguments = '/install /quiet /norestart' + #endregion PossibleParameters + + #region Defaults + # Set the full path of the downloaded installer + [string]$InstallerPackage = ($Target + '\' + $TargetName) + + $SCT = 'SilentlyContinue' + $STP = 'Stop' + #endregion Defaults +} + +process +{ + # Use BitsTransfer to download the latest installer + $paramStartBitsTransfer = @{ + Source = $SkypeOnlinePowerShellUrl + Destination = $InstallerPackage + Priority = 'Foreground' + TransferPolicy = 'Always' + ErrorAction = $STP + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + + + $paramTestPath = @{ + Path = $InstallerPackage + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $InstallerPackage + ErrorAction = $SCT + } + $InstallerVersion = ((Get-ItemProperty @paramGetItemProperty).VersionInfo.ProductVersion) + + Write-Verbose -Message ('Running SkypeOnlinePowerShell installer version {0}' -f $InstallerVersion) + + $paramStartProcess = @{ + FilePath = $InstallerPackage + ArgumentList = $Arguments + Wait = $true + PassThru = $true + ErrorAction = $STP + } + $InstallerProcess = (Start-Process @paramStartProcess) + + if (($InstallerProcess | Select-Object -ExpandProperty ExitCode) -eq 0) + { + Write-Verbose -Message ('Installed FSLogix version {0}' -f $InstallerVersion) + } + else + { + Write-Warning -Message ('Installer exit code {0}.' -f $InstallerProcess.ExitCode) + } + + Write-Verbose -Message ('Removing file: {0}' -f $InstallerPackage) + + # Remove the downloaded Installaer Package + $paramRemoveItem = @{ + Path = $InstallerPackage + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-WingetFromRepositoryRelease.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-WingetFromRepositoryRelease.ps1 new file mode 100644 index 0000000..8317f18 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Install-WingetFromRepositoryRelease.ps1 @@ -0,0 +1,147 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Download and install the latest WinGet release from GitHub + + .DESCRIPTION + Download and install the latest WinGet release from GitHub + + .NOTES + Version 1.0.1 + + Original Script by Adriano Cahete +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + $BaseDirectory = 'c:\install\files\' + + # Download latest release from GitHub + $Repo = 'https://api.github.com/repos/microsoft/winget-cli/releases/latest' +} + +process +{ + # Query the API to get the url of the zip + $paramInvokeRestMethod = @{ + Method = 'Get' + Uri = $Repo + ErrorAction = 'Stop' + } + $APIResponse = (Invoke-RestMethod @paramInvokeRestMethod) + $FileUrl = $APIResponse.assets.browser_download_url + + # Download the file to the current location + $fileName = "$($APIResponse.name.Replace(' ', '_')).appxbundle" + $OutputPath = ($BaseDirectory + $fileName) + + $paramTestPath = @{ + Path = $BaseDirectory + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $BaseDirectory + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramPushLocation = @{ + Path = $BaseDirectory + ErrorAction = $SCT + } + $null = (Push-Location @paramPushLocation) + + Write-Verbose -Message "Downloading $fileName ...`n" + + $paramInvokeRestMethod = @{ + Method = 'Get' + Uri = $FileUrl + OutFile = $OutputPath + ErrorAction = 'Stop' + } + $null = (Invoke-RestMethod @paramInvokeRestMethod) + + $paramTestPath = @{ + Path = $OutputPath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + Write-Verbose -Message "`nInstalling $fileName ...`n" + + $paramAddAppxPackage = @{ + Path = $OutputPath + ForceTargetApplicationShutdown = $true + InstallAllResources = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Add-AppxPackage @paramAddAppxPackage) + + $null = (Pop-Location -ErrorAction $SCT) + + # TODO: Check + if (Test-Path -Path 'C:\ProgramData\chocolatey\bin\RefreshEnv.cmd' -ErrorAction $SCT) + { + C:\ProgramData\chocolatey\bin\RefreshEnv.cmd + } + + try + { + $WinGetVersion = (winget.exe --version) + Write-Output -InputObject "WinGet version is: $WinGetVersion" + Write-Output -InputObject "`WinGet is installed. Try to run the 'winget' command.`n" + } + catch + { + Write-Error -Message "`WinGet is not installed. Try to install from MS Store instead`n" -ErrorAction Stop + } + } + else + { + Write-Error -Message "`WinGet Installer not found. Try to install from MS Store instead`n" -ErrorAction Stop + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +# ============================================================= +# Copyright 2020 Adriano Cahete +# TODO: Add License +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============================================================= + +# Install Winget +# TODO: Check windows version +# TODO: Check if it's easier to get from repository or MS Store +# TODO: Check if Sideloading is enabled - https://docs.microsoft.com/en-us/windows/uwp/get-started/enable-your-device-for-development +# TODO: Do the option to enable sideloading from PS console (I don't know even it's possible) +# TODO: Clear old files before start diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BackupBitLockerKeyToAAD.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BackupBitLockerKeyToAAD.ps1 new file mode 100644 index 0000000..fe84c9a --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BackupBitLockerKeyToAAD.ps1 @@ -0,0 +1,173 @@ +#requires -Version 2.0 -RunAsAdministrator + +<# + .SYNOPSIS + Backup all BitLocker Recovery Key to AzureAD + + .DESCRIPTION + Backup all BitLocker Recovery Key to AzureAD + + .EXAMPLE + PS C:\> .\Invoke-BackupBitLockerKeyToAAD.ps1 + + .NOTES + Version 1.0.0 + + The multiple recovery passwords part is still unstable +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + Write-Output -InputObject 'Backup all BitLocker Recovery Key to AzureAD' + + $SCT = 'SilentlyContinue' + $STP = 'Stop' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + $keyID = $null + + $paramGetBitLockerVolume = @{ + MountPoint = $env:systemdrive + ErrorAction = $SCT + WarningAction = $SCT + } + $keyID = (Get-BitLockerVolume @paramGetBitLockerVolume | Select-Object -ExpandProperty keyprotector | Where-Object -FilterScript { + $_.KeyProtectorType -eq 'RecoveryPassword' + }) +} + +process +{ + try + { + if (-not $keyID) + { + # In case there is no Recovery Password, lets create new one + $paramAddBitLockerKeyProtector = @{ + MountPoint = $env:systemdrive + RecoveryPasswordProtector = $true + ErrorAction = $STP + WarningAction = $SCT + Confirm = $false + } + $null = (Add-BitLockerKeyProtector @paramAddBitLockerKeyProtector) + + $paramGetBitLockerVolume = @{ + MountPoint = $env:systemdrive + ErrorAction = $SCT + WarningAction = $SCT + } + $paramGetBitLockerVolume = @{ + MountPoint = $env:systemdrive + ErrorAction = $STP + WarningAction = $SCT + } + $keyID = (Get-BitLockerVolume @paramGetBitLockerVolume | Select-Object -ExpandProperty keyprotector | Where-Object -FilterScript { + $_.KeyProtectorType -eq 'RecoveryPassword' + }) + } + } + catch + { + throw + break + } + + $paramBackupToAADBitLockerKeyProtector = @{ + MountPoint = $env:systemdrive + ErrorAction = $STP + WarningAction = $SCT + } + + if ($keyID.Count -cgt 1) + { + for ($i = 0; $i -le $keyID.Count; $i++) + { + if ($keyID[$i]) + { + Write-Verbose -Message ('Start Backup BitLockerKey {0}' -f $i) + + try + { + $paramBackupToAADBitLockerKeyProtector = @{ + KeyProtectorId = $keyID.KeyProtectorId[$i] + MountPoint = $env:systemdrive + ErrorAction = $STP + WarningAction = $SCT + } + $null = (BackupToAAD-BitLockerKeyProtector @paramBackupToAADBitLockerKeyProtector) + + Write-Verbose -Message ('Done Backup BitLockerKey {0}' -f $i) + } + catch + { + Write-Warning -Message ('Unable to Backup BitLockerKey {0}' -f $i) + } + } + } + } + else + { + Write-Verbose -Message 'Start Backup BitLockerKey' + + try + { + $paramBackupToAADBitLockerKeyProtector = @{ + KeyProtectorId = $keyID.KeyProtectorId + MountPoint = $env:systemdrive + ErrorAction = $STP + WarningAction = $SCT + } + $null = (BackupToAAD-BitLockerKeyProtector @paramBackupToAADBitLockerKeyProtector) + + Write-Verbose -Message 'Done Backup BitLockerKey' + } + catch + { + Write-Warning -Message 'Unable to Backup BitLockerKey' + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapAllUserProfile.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapAllUserProfile.ps1 new file mode 100644 index 0000000..96007f4 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapAllUserProfile.ps1 @@ -0,0 +1,1902 @@ +#requires -Version 5.0 -RunAsAdministrator + +<# + .SYNOPSIS + Tweak the All User Profiles + + .DESCRIPTION + Tweak the All User Profiles + + .NOTES + Still beta! + + Version 2.0.5 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Tweak the All User Profiles' + + $SCT = 'SilentlyContinue' + + $ErrorActionPreference = $SCT + + $paramGetCommand = @{ + Name = 'Set-MpPreference' + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Disabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + } + + $paramRemoveItemProperty = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + #endregion GlobalDefaults + + #region + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object -FilterScript { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + #endregion + + #region HelperFunction + function Confirm-RegistryItemProperty + { + <# + .SYNOPSIS + Enforce that an item property in the registry + + .DESCRIPTION + Enforce that an item property in the registry + + .PARAMETER Path + Registry Path + + .PARAMETER PropertyType + The Property Type + + .PARAMETER Value + The Registry Value to set + + .EXAMPLE + PS C:\> Confirm-RegistryItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\PimIndexMaintenanceSvc\Start' -PropertyType 'DWord' -Value '1' + + .NOTES + Fixed version of the Helper: + Recreate the Key if the Type is wrong (Possible cause the old version had a glitsch) + #> + [CmdletBinding(ConfirmImpact = 'None', SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [Alias('RegistryPath')] + [string] + $Path, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [Alias('Property', 'Type')] + [string] + $PropertyType, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [AllowNull()] + [Alias('RegistryValue')] + $Value + ) + + begin + { + #region + $SCT = 'SilentlyContinue' + #endregion + } + + process + { + $paramTestPath = @{ + Path = ($Path | Split-Path) + WarningAction = $SCT + ErrorAction = $SCT + } + if (-Not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = ($Path | Split-Path) + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramGetItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + WarningAction = $SCT + ErrorAction = $SCT + } + if (-Not (Get-ItemProperty @paramGetItemProperty)) + { + $paramNewItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + PropertyType = $PropertyType + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + #region Workaround + $paramGetItem = @{ + Path = ($Path | Split-Path) + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-Item @paramGetItem).GetValueKind(($Path | Split-Path -Leaf))) -ne $PropertyType) + { + # The PropertyType is wrong! This might be an issue of our old version! Sorry for the glitsch + $paramRemoveItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-ItemProperty @paramRemoveItemProperty) + + $paramNewItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + PropertyType = $PropertyType + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + # Regular handling: PropertyType was correct + $paramSetItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + #endregion Workaround + } + } + } + #endregion HelperFunction +} + +process +{ + # Stop Search - Gain performance + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object -FilterScript { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Get default user profile path + $paramGetItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList' + Name = 'Default' + ErrorAction = $SCT + WarningAction = $SCT + } + $DefaultUserProfile = ((Get-ItemProperty @paramGetItemProperty).Default) + + # Modify default startmenu and remove all tiles which will be downloaded later + $paramJoinPath = @{ + Path = $DefaultUserProfile + ChildPath = 'AppData\Local\Microsoft\Windows\Shell\DefaultLayouts.xml' + ErrorAction = $SCT + WarningAction = $SCT + } + $XmlObjectPath = (Join-Path @paramJoinPath) + $paramNewObject = @{ + TypeName = 'xml' + ErrorAction = $SCT + WarningAction = $SCT + } + $XmlObject = (New-Object @paramNewObject) + $XmlObject.PreserveWhitespace = $true + $null = ($XmlObject.Load($XmlObjectPath)) + $paramNewObject = @{ + TypeName = 'System.Xml.XmlNamespaceManager' + ArgumentList = ($XmlObject.NameTable) + ErrorAction = $SCT + WarningAction = $SCT + } + $XmlNameSpace = (New-Object @paramNewObject) + $null = ($XmlNameSpace.AddNamespace('start', 'http://schemas.microsoft.com/Start/2014/StartLayout')) + $null = ($XmlObject.SelectNodes('//start:SecondaryTile', $XmlNameSpace) | ForEach-Object -Process { + $null = $_.ParentNode.RemoveChild($_) + }) + $null = ($XmlObject.Save($XmlObjectPath)) + + # Easy HKU access + $paramNewPSDrive = @{ + PSProvider = 'Registry' + Name = 'HKU' + Root = 'HKEY_USERS' + ErrorAction = $SCT + } + $null = (New-PSDrive @paramNewPSDrive) + + # Load default user hive + $null = (& "$env:windir\system32\reg.exe" load 'HKU\DEFAULT' (Join-Path -Path $DefaultUserProfile -ChildPath 'NTUSER.DAT' -ErrorAction $SCT -WarningAction $SCT)) + + #region Modifications + + #region PrivacyTweaks + #region DisableWindowsErrorDialog + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\Windows Error Reporting\DontShowUI' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWindowsErrorDialog + + #region DisableAdvertisingInfo + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAdvertisingInfo + + #region DisableWebSearch + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search\BingSearchEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search\CortanaConsent' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWebSearch + + #region + # Do not suggest ways I can finish setting up my device to get the most out of Windows (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\UserProfileEngagement\ScoobeSystemSettingEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region DisableAppSuggestions + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\ContentDeliveryAllowed' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\OemPreInstalledAppsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\PreInstalledAppsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\PreInstalledAppsEverEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SilentInstalledAppsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-310093Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-314559Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338387Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-353694Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338388Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338389Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338393Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338388Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-353696Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-353698Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SystemPaneSuggestionsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Empty placeholder tile collection in registry cache and restart Start Menu process to reload the cache + if ([Environment]::OSVersion.Version.Build -ge 17134) + { + $paramGetItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\*windows.data.placeholdertilecollection\Current' + WarningAction = $SCT + ErrorAction = $SCT + } + $key = (Get-ItemProperty @paramGetItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = ($key.PSPath + 'Data') + PropertyType = 'Binary' + Value = $key.Data[0 .. 15] + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramStopProcess = @{ + Name = 'ShellExperienceHost' + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Stop-Process @paramStopProcess) + } + #endregion DisableAppSuggestions + + #region DisableActivityHistory + #endregion DisableActivityHistory + + #region DisableBackgroundApps + $paramGetChildItem = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications' + Exclude = 'Microsoft.Windows.Cortana*', 'Microsoft.Windows.ShellExperienceHost*' + WarningAction = $SCT + ErrorAction = $SCT + } + + $null = (Get-ChildItem @paramGetChildItem | ForEach-Object -Process { + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + 'Disabled') + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + 'DisabledByUser') + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + }) + #endregion DisableBackgroundApps + + #region + # Make the "Open", "Print", "Edit" context menu items available, when more than 15 selected + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MultipleInvokePromptMinimum' + PropertyType = 'DWord' + Value = '300' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region DisableFeedback + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Siuf\Rules\NumberOfSIUFInPeriod' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableFeedback + + #region DisableTailoredExperiences + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Privacy\TailoredExperiencesWithDiagnosticDataEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableTailoredExperiences + + #region DisableAdvertisingID + #endregion DisableAdvertisingID + + #region DisableWebLangList + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\International\User Profile\HttpAcceptLanguageOptOut' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWebLangList + + #region DisableCortana + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Personalization\Settings\AcceptedPrivacyPolicy' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\InputPersonalization\RestrictImplicitTextCollection' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\InputPersonalization\RestrictImplicitInkCollection' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\InputPersonalization\TrainedDataStore\HarvestContacts' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableCortana + #endregion PrivacyTweaks + + #region SecurityTweaks + #region + # Turn off Windows Script Host (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows Script Host\Settings\Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region AppAndBrowser_EdgeSmartScreenOff + # Dismiss Microsoft Defender offer in the Windows Security about to turn on the SmartScreen filter for Microsoft Edge + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows Security Health\State\AppAndBrowser_EdgeSmartScreenOff' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion AppAndBrowser_EdgeSmartScreenOff + + #region HideDefenderAccountProtectionWarning + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows Security Health\State\AccountProtection_MicrosoftAccount_Disconnected' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideDefenderAccountProtectionWarning + + #region DisableDownloadBlocking + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Attachments\SaveZoneInformation' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableDownloadBlocking + #endregion SecurityTweaks + + #region LegacyDefaultPrinterMode + # Do not let Windows manage default printer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Windows\LegacyDefaultPrinterMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion LegacyDefaultPrinterMode + + #region ServiceTweaks + #region DisableSharedExperiences + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CDP\RomeSdkChannelUserAuthzPolicy' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableSharedExperiences + + #region DisableClipboardHistory + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Clipboard' -Name 'EnableClipboardHistory' @paramRemoveItemProperty) + #endregion DisableClipboardHistory + + #region DisableAutoplay + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers\DisableAutoplay' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAutoplay + + #region + # Automatically save my restartable apps when signing out and restart them after signing in (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\RestartApps' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region EnableStorageSense + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\01' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\StoragePoliciesNotified' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Run Storage Sense every month + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\2048' + PropertyType = 'DWord' + Value = '30' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Delete temporary files that apps aren't using + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\04' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Delete files in recycle bin if they have been there for over 30 days + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\08' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\256' + PropertyType = 'DWord' + Value = '30' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Never delete files in "Downloads" folder + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\512' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableStorageSense + + #region EnableRecycleBin + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' -Name 'NoRecycleFiles' @paramRemoveItemProperty) + #endregion EnableRecycleBin + #endregion ServiceTweaks + + #region UITweaks + #region EnablePerProcessSystemDPI + # Let Windows try to fix apps so they're not blurry + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\EnablePerProcessSystemDPI' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnablePerProcessSystemDPI + + #region EnableActionCenter + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Policies\Microsoft\Windows\Explorer' -Name 'DisableNotificationCenter' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\PushNotifications' -Name 'ToastEnabled'@paramRemoveItemProperty) + #endregion EnableActionCenter + + #region EnableAeroShake + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'DisallowShaking' @paramRemoveItemProperty) + #endregion EnableAeroShake + + #region DisableAccessibilityKeys + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\StickyKeys\Flags' + PropertyType = 'String' + Value = '506' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\ToggleKeys\Flags' + PropertyType = 'String' + Value = '58' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\Keyboard Response\Flags' + PropertyType = 'String' + Value = '122' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAccessibilityKeys + + #region ShowTaskManagerDetails + $paramStartProcess = @{ + WindowStyle = 'Hidden' + FilePath = 'taskmgr.exe' + PassThru = $true + WarningAction = $SCT + ErrorAction = $SCT + } + + $taskmgr = (Start-Process @paramStartProcess) + $timeout = 30000 + $sleep = 100 + $preferences = $null + do + { + $null = (Start-Sleep -Milliseconds $sleep) + $timeout -= $sleep + $paramGetItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\TaskManager' + Name = 'Preferences' + WarningAction = $SCT + ErrorAction = $SCT + } + + $preferences = (Get-ItemProperty @paramGetItemProperty) + } + until ($preferences -or $timeout -le 0) + $null = ($taskmgr | Stop-Process -WarningAction $SCT -ErrorAction $SCT) + + if ($preferences) + { + $preferences.Preferences[28] = 0 + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\TaskManager\Preferences' + PropertyType = 'Binary' + Value = $preferences.Preferences + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + #endregion ShowTaskManagerDetails + + #region ShowFileOperationsDetails + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\OperationStatusManager\EnthusiastMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowFileOperationsDetails + + #region EnableFileDeleteConfirm + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ConfirmFileDelete' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableFileDeleteConfirm + + #region HideTaskbarSearch + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search\SearchboxTaskbarMode' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideTaskbarSearch + + #region HideTaskView + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowTaskViewButton' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideTaskView + + #region ShowSmallTaskbarIcons + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\TaskbarSmallIcons' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowSmallTaskbarIcons + + #region SetTaskbarCombineAlways + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'TaskbarGlomLevel' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'MMTaskbarGlomLevel' @paramRemoveItemProperty) + #endregion SetTaskbarCombineAlways + + #region HideTaskbarPeopleIcon + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People\PeopleBand' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideTaskbarPeopleIcon + + #region HideTrayIcons + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' -Name 'NoAutoTrayNotify' @paramRemoveItemProperty) + #endregion HideTrayIcons + + #region HideSecondsFromTaskbar + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'ShowSecondsInSystemClock' @paramRemoveItemProperty) + #endregion HideSecondsFromTaskbar + + #region SetControlPanelSmallIcons + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\StartupPage' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\AllItemsIconView' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetControlPanelSmallIcons + + #region DisableShortcutInName + $paramNewItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\' + Name = 'link' + PropertyType = 'Binary' + Value = ([byte[]](00, 00, 00, 00)) + Force = $true + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion DisableShortcutInName + + #region PrintScreenKeyForSnippingEnabled + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Keyboard\PrintScreenKeyForSnippingEnabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion PrintScreenKeyForSnippingEnabled + + #region SetVisualFXPerformance + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\DragFullWindows' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\MenuShowDelay' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\UserPreferencesMask' + PropertyType = 'Binary' + Value = ([byte[]](144, 18, 3, 128, 16, 0, 0, 0)) + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\WindowMetrics\MinAnimate' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Keyboard\KeyboardDelay' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewAlphaSelect' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\TaskbarAnimations' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects\VisualFXSetting' + PropertyType = 'DWord' + Value = 3 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\DWM\EnableAeroPeek' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetVisualFXPerformance + + #region EnableTitleBarColor + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\DWM\ColorPrevalence' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableTitleBarColor + + #region DisableDynamicScrollbars + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\DynamicScrollbars' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableDynamicScrollbars + + #region RemoveENKeyboard + $langs = (Get-WinUserLanguageList -ErrorAction $SCT) + $null = (Set-WinUserLanguageList -LanguageList ($langs | Where-Object { + $_.LanguageTag -ne 'en-US' + }) -Force -ErrorAction $SCT) + #endregion RemoveENKeyboard + + #region EnableEnhPointerPrecision + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Mouse\MouseSpeed' + PropertyType = 'String' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Mouse\MouseThreshold1' + PropertyType = 'String' + Value = '6' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Mouse\MouseThreshold2' + PropertyType = 'String' + Value = '10' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableEnhPointerPrecision + + #region DisableLiveTilesPermanently + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\NoTileApplicationNotification' + PropertyType = 'String' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableLiveTilesPermanently + + #region ToastNotificationsToTop + # Move Toast Notifications to Top of Screen + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DisplayToastAtBottom' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ToastNotificationsToTop + + #region SetSoundSchemeNone + $SoundScheme = '.None' + $paramGetChildItem = @{ + Path = 'HKCU:\AppEvents\Schemes\Apps\*\*' + ErrorAction = $SCT + } + $null = (Get-ChildItem @paramGetChildItem | ForEach-Object { + # If scheme keys do not exist in an event, create empty ones (similar behavior to Sound control panel). + $paramTestPath = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramTestPath = @{ + Path = ($_.PsPath + '\.Current') + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = ($_.PsPath + '\.Current') + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + # Get a regular string from any possible kind of value, i.e. resolve REG_EXPAND_SZ, copy REG_SZ or empty from non-existing. + $paramGetItemProperty = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + Name = '(Default)' + ErrorAction = $SCT + } + $Data = ((Get-ItemProperty @paramGetItemProperty).'(Default)') + + if ($Data) + { + # Replace any kind of value with a regular string (similar behavior to Sound control panel). + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + Name = '(Default)' + PropertyType = 'String' + Value = $Data + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Copy data from source scheme to current. + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + '\.Current') + Name = '(Default)' + PropertyType = 'String' + Value = $Data + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + }) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\AppEvents\Schemes\(Default)' + PropertyType = 'String' + Value = $SoundScheme + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetSoundSchemeNone + + #region DisableF1HelpKey + $paramTestPath = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32' + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32' + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32\(Default)' + PropertyType = 'String' + Value = '' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramTestPath = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64' + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64' + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64\(Default)' + PropertyType = 'String' + Value = '' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableF1HelpKey + #endregion UITweaks + + #region ExplorerUITweaks + #region DisableXboxGamebar + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\GameDVR\AppCaptureEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\GameBar\ShowStartupPanel' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableXboxGamebar + + #region HideExplorerTitleFullPath + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState' -Name 'FullPath' @paramRemoveItemProperty) + #endregion HideExplorerTitleFullPath + + #region ShowKnownExtensions + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideFileExt' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowKnownExtensions + + #region ShowHiddenFiles + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Hidden' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowHiddenFiles + + #region HideSuperHiddenFiles + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowSuperHidden' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideSuperHiddenFiles + + #region ShowEmptyDrives + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideDrivesWithNoMedia' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowEmptyDrives + + #region ShowFolderMergeConflicts + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideMergeConflicts' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowFolderMergeConflicts + + #region EnableNavPaneExpand + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\NavPaneExpandToCurrentFolder' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableNavPaneExpand + + #region MMTaskbarMode + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\MMTaskbarMode' + PropertyType = 'DWord' + Value = '2' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion MMTaskbarMode + + #region HideNavPaneAllFolders + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'NavPaneShowAllFolders' @paramRemoveItemProperty) + #endregion HideNavPaneAllFolders + + #region EnableFolderSeparateProcess + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\SeparateProcess' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableFolderSeparateProcess + + #region DisableRestoreFldrWindows + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'PersistBrowsers' @paramRemoveItemProperty) + #endregion DisableRestoreFldrWindows + + #region ShowEncCompFilesColor + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowEncryptCompressedColor' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowEncCompFilesColor + + #region DisableSharingWizard + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\SharingWizardOn' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableSharingWizard + + #region ShowSelectCheckboxes + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\AutoCheckSelect' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowSelectCheckboxes + + #region ShowSyncNotifications + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowSyncProviderNotifications' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowSyncNotifications + + #region HideRecentShortcuts + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ShowRecent' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ShowFrequent' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideRecentShortcuts + + #region SetExplorerThisPC + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\LaunchTo' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetExplorerThisPC + + #region HideQuickAccess + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HubMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideQuickAccess + + #region ShowRecycleBinOnDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{645FF040-5081-101B-9F08-00AA002F954E}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{645FF040-5081-101B-9F08-00AA002F954E}' @paramRemoveItemProperty) + #endregion ShowRecycleBinOnDesktop + + #region ShowThisPCOnDesktop + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu\{20D04FE0-3AEA-1069-A2D8-08002B30309D}' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel\{20D04FE0-3AEA-1069-A2D8-08002B30309D}' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowThisPCOnDesktop + + #region HideUserFolderFromDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{59031a47-3f72-44a7-89c5-5595fe6b30ee}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{59031a47-3f72-44a7-89c5-5595fe6b30ee}' @paramRemoveItemProperty) + #endregion HideUserFolderFromDesktop + + #region HideControlPanelFromDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}' @paramRemoveItemProperty) + #endregion HideControlPanelFromDesktop + + #region HideNetworkFromDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}' @paramRemoveItemProperty) + #endregion HideNetworkFromDesktop + + #region HideBuildNumberFromDesktop + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\PaintDesktopVersion' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideBuildNumberFromDesktop + + #region ScreenSaver + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\ScreenSaveActive' + PropertyType = 'String' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\ScreenSaverIsSecure' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\ScreenSaveTimeOut' + PropertyType = 'DWord' + Value = '600' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\scrnsave.exe' + PropertyType = 'String' + Value = ($env:windir + '\system32\scrnsave.scr') + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ScreenSaver + + #region + # Do not add the "- Shortcut" suffix to the file name of created shortcuts (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NamingTemplates\ShortcutNameTemplate' + PropertyType = 'String' + Value = '%s.lnk' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region DisableThumbnails + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\IconsOnly' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableThumbnails + + #region DisableThumbnailCache + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\DisableThumbnailCache' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableThumbnailCache + + #region DisableThumbsDBOnNetwork + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\DisableThumbsDBOnNetworkFolders' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableThumbsDBOnNetwork + + #region DisableDesktopWallpaperQualityReduction + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\JPEGImportQuality' + PropertyType = 'DWord' + Value = '100' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableDesktopWallpaperQualityReduction + + #region RemoveMicrosoftEdgeShortcut + $paramGetItemPropertyValue = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders' + Name = 'Desktop' + ErrorAction = $SCT + } + $Value = (Get-ItemPropertyValue @paramGetItemPropertyValue) + $null = (Remove-Item -Path ($Value + '\Microsoft Edge.lnk') @paramRemoveItemProperty) + #endregion RemoveMicrosoftEdgeShortcut + + #region RemoveHPSupportAssistantShortcut + $null = (Remove-Item -Path "$env:PUBLIC\Desktop\HP Support Assistant.lnk" @paramRemoveItemProperty) + #endregion RemoveHPSupportAssistantShortcut + #endregion ExplorerUITweaks + + #region ApplicationTweaks + #region DisableFullscreenOptims + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_DXGIHonorFSEWindowsCompatible' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_FSEBehavior' + PropertyType = 'DWord' + Value = 2 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_FSEBehaviorMode' + PropertyType = 'DWord' + Value = 2 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_HonorUserFSEBehaviorMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableFullscreenOptims + + if (-not ($env:COMPUTERNAME -match 'ENSHARED-')) + { + #region OneDriveInsider + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\OneDrive\EnableTeamTier_Internal' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\OneDrive\EnableFasterRingUpdate' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion OneDriveInsider + + #region EnableADALOneDrive + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\OneDrive\EnableADAL' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableADALOneDrive + + #region OneDriveEnableHoldTheFile + # Users can choose how to handle Office files in conflict + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\OneDrive\EnableHoldTheFile' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregionEnableHoldTheFile + + #region OneDriveEnableAllOcsiClients + # Coauthoring and in-app sharing for Office files + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\OneDrive\EnableAllOcsiClients' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion OneDriveEnableAllOcsiClients + } + #endregion ApplicationTweaks + + #region Unpinning + #region UnpinStartMenuTiles + # TODO: Convert to Switch + <# + if ([Environment]::OSVersion.Version.Build -ge 15063 -And [Environment]::OSVersion.Version.Build -le 16299) + { + Get-ChildItem -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount' -Include '*.group' -Recurse -WarningAction $SCT -ErrorAction $SCT | ForEach-Object { + $Data = ((Get-ItemProperty -Path ($_.PsPath + '\Current') -Name 'Data' -WarningAction $SCT -ErrorAction $SCT).Data -Join ',') + $Data = ($Data.Substring(0, $Data.IndexOf(',0,202,30') + 9) + ',0,202,80,0,0') + + $null = (Confirm-RegistryItemProperty -Path ($_.PsPath + '\Current\Data') -PropertyType Binary -Value $Data.Split(',') -WarningAction $SCT -ErrorAction $SCT) + } + } + elseif ([Environment]::OSVersion.Version.Build -ge 17134) + { + $key = (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\*start.tilegrid`$windows.data.curatedtilecollection.tilecollection\Current" -WarningAction $SCT -ErrorAction $SCT) + $Data = $key.Data[0 .. 25] + ([byte[]](202, 50, 0, 226, 44, 1, 1, 0, 0)) + + $null = (Confirm-RegistryItemProperty -Path ($key.PSPath + '\Data') -PropertyType Binary -Value $Data -ErrorAction $SCT) + + $null = (Stop-Process -Name 'ShellExperienceHost' -Force -WarningAction $SCT -ErrorAction $SCT) + } + #> + #endregion UnpinStartMenuTiles + + #region UnpinTaskbarIcons + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband\Favorites' + PropertyType = 'Binary' + Value = ([byte[]](255)) + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband' -Name 'FavoritesResolve' @paramRemoveItemProperty) + #endregion UnpinTaskbarIcons + #endregion Unpinning + + #region FinalTouches + #region PowerShellProfiles + # Create all PowerShell related Profiles as dummy (empty) + $AllSystemProfiles = @( + (($PROFILE).CurrentUserCurrentHost) + (($PROFILE).CurrentUserAllHosts) + (($PROFILE).AllUsersCurrentHost) + (($PROFILE).AllUsersAllHosts) + ($PSHOME + '\Microsoft.VSCode_profile.ps1') + ) + + foreach ($SystemProfile in $AllSystemProfiles) + { + $paramTestPath = @{ + Path = $SystemProfile + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + ItemType = 'File' + Path = $SystemProfile + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + } + #endregion PowerShellProfiles + + # Restart Start menu + $paramStopProcess = @{ + Name = 'StartMenuExperienceHost' + Force = $true + ErrorAction = $SCT + } + $null = (Stop-Process @paramStopProcess) + + # Refresh desktop icons, environment variables and taskbar without restarting File Explorer + $UpdateEnvExplorerAPI = @{ + Namespace = 'WinAPI' + Name = 'UpdateEnvExplorer' + Language = 'CSharp' + MemberDefinition = @' +private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff); +private const int WM_SETTINGCHANGE = 0x1a; +private const int SMTO_ABORTIFHUNG = 0x0002; +[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] +static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam); +[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] +private static extern IntPtr SendMessageTimeout(IntPtr hWnd, int Msg, IntPtr wParam, string lParam, int fuFlags, int uTimeout, IntPtr lpdwResult); +[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = false)] +private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); +public static void Refresh() +{ + // Update desktop icons + SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero); + // Update environment variables + SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero); + // Update taskbar + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, "TraySettings"); +} +'@ + } + + if (-not ('WinAPI.UpdateEnvExplorer' -as [type])) + { + $null = (Add-Type @UpdateEnvExplorerAPI) + } + + $null = ([WinAPI.UpdateEnvExplorer]::Refresh()) + #endregion FinalTouches + + #endregion Modifications + + #region SetupRunOnce + #In case we apply any updates + + $RunOneOnjectPath = 'C:\scripts\PowerShell\Invoke-BootstrapUser.ps1' + + $RunOnceHku = 'HKU:\DEFAULT\Software\Microsoft\Windows\CurrentVersion\RunOnce' + $paramNewItem = @{ + Path = $RunOnceHku + Force = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + + $paramNewItemProperty = @{ + Path = $RunOnceHku + Force = $true + Name = '!run_once' + Value = "powershell -NoProfile -WindowStyle Hidden -File $RunOneOnjectPath" + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + + $RuneOnceHkcu = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\RunOnce' + $paramNewItem = @{ + Path = $RuneOnceHkcu + Force = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + + $paramNewItemProperty = @{ + Path = $RuneOnceHkcu + Force = $true + Name = '!run_once' + Value = "powershell -NoProfile -WindowStyle Hidden -File $RunOneOnjectPath" + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion SetupRunOnce + + # unload default user hive + $null = (& "$env:windir\system32\reg.exe" unload 'HKU\DEFAULT') + + try + { + $paramRemovePSDrive = @{ + Name = 'HKU' + Force = $true + ErrorAction = $SCT + WarningAction = $SCT + } + + $null = (Remove-PSDrive @paramRemovePSDrive) + } + catch + { + Write-Verbose -Message 'Known issue' + } +} + +end +{ + $null = ([GC]::Collect()) + + $paramGetCommand = @{ + Name = 'Set-MpPreference' + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Enabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapSystem.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapSystem.ps1 new file mode 100644 index 0000000..c393917 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapSystem.ps1 @@ -0,0 +1,3443 @@ +#requires -Version 5.0 -RunAsAdministrator + +<# + .SYNOPSIS + Bootstrap Windows 10 System + + .DESCRIPTION + Bootstrap Windows 10 System with the default configuration. + Tested with the latest Windows 10 (Enterprise and Professional) releases. + + .NOTES + Changelog: + 2.0.9: Windows Hello Video is no longer removed (Requested) + 2.0.8: Removed the Enable DNS-over-HTTPS part (own script) + 2.0.7: Add a few more tweaks + 2.0.6: Add "Make Me Admin" default config + 2.0.5: Change a few handlers for WindowsFeatures + 2.0.4: Remove Edge icon on desktop + 2.0.3: Remove the 20H2 Edge Autostart + 2.0.2: Remove First Run Experience for Edge + + Version 2.2.0 + + Lot of the stuff of this version is adopted from Disassembler + + .LINK + http://enatec.io + + .LINK + https://github.com/Disassembler0/Win10-Initial-Setup-Script +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Bootstrap Windows 10 System' + + #region GlobalDefaults + $SCT = 'SilentlyContinue' + + $paramGetCommand = @{ + Name = 'Set-MpPreference' + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Disabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + } + + $paramRemoveItemProperty = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + #endregion GlobalDefaults + + #region HelperFunction + function Confirm-RegistryItemProperty + { + <# + .SYNOPSIS + Enforce that an item property in the registry + + .DESCRIPTION + Enforce that an item property in the registry + + .PARAMETER Path + Registry Path + + .PARAMETER PropertyType + The Property Type + + .PARAMETER Value + The Registry Value to set + + .EXAMPLE + PS C:\> Confirm-RegistryItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\PimIndexMaintenanceSvc\Start' -PropertyType 'DWord' -Value '1' + + .NOTES + Fixed version of the Helper: + Recreate the Key if the Type is wrong (Possible cause the old version had a glitsch) + #> + [CmdletBinding(ConfirmImpact = 'None', SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [Alias('RegistryPath')] + [string] + $Path, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [Alias('Property', 'Type')] + [string] + $PropertyType, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [AllowNull()] + [Alias('RegistryValue')] + $Value + ) + + begin + { + #region + $SCT = 'SilentlyContinue' + #endregion + } + + process + { + $paramTestPath = @{ + Path = ($Path | Split-Path) + WarningAction = $SCT + ErrorAction = $SCT + } + if (-Not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = ($Path | Split-Path) + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramGetItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + WarningAction = $SCT + ErrorAction = $SCT + } + if (-Not (Get-ItemProperty @paramGetItemProperty)) + { + $paramNewItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + PropertyType = $PropertyType + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + #region Workaround + $paramGetItem = @{ + Path = ($Path | Split-Path) + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-Item @paramGetItem).GetValueKind(($Path | Split-Path -Leaf))) -ne $PropertyType) + { + # The PropertyType is wrong! This might be an issue of our old version! Sorry for the glitsch + $paramRemoveItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-ItemProperty @paramRemoveItemProperty) + + $paramNewItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + PropertyType = $PropertyType + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + # Regular handling: PropertyType was correct + $paramSetItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + #endregion Workaround + } + } + } + #endregion HelperFunction +} + +process +{ + # Stop Search - Gain performance + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object -FilterScript { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + #region PrivacyTweaks + # Turn off the "Previous Versions" tab from properties context menu + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NoPreviousVersionsPage' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Do not use sign-in info to automatically finish setting up device after an update or restart + $paramGetCimInstance = @{ + ClassName = 'Win32_UserAccount' + ErrorAction = $SCT + WarningAction = $SCT + } + $sid = ((Get-CimInstance @paramGetCimInstance | Where-Object -FilterScript { + $_.Name -eq ($env:USERNAME) + }).SID) + $paramConfirmRegistryItemProperty = @{ + Path = ('HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\UserARSO\' + $sid + 'OptOut') + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + #region DisableTelemetry + $paramGetWindowsEdition = @{ + Online = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $WindowsEditionEdition = ((Get-WindowsEdition @paramGetWindowsEdition) | Select-Object -ExpandProperty Edition) + + if (($WindowsEditionEdition -eq 'Enterprise') -or ($WindowsEditionEdition -eq 'Education')) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\AllowTelemetry' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + else + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\AllowTelemetry' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection\AllowTelemetry' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection\AllowTelemetry' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PreviewBuilds\AllowBuildPreview' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\Software Protection Platform\NoGenTicket' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\SQMClient\Windows\CEIPEnable' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppCompat\AITEnable' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppCompat\DisableInventory' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\AppV\CEIP\CEIPEnable' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\TabletPC\PreventHandwritingDataSharing' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\TextInput\AllowLinguisticDataCollection' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramGetScheduledTask = @{ + TaskName = 'Microsoft Compatibility Appraiser', 'ProgramDataUpdater', 'Consolidator', 'KernelCeipTask', 'UsbCeip', 'Microsoft-Windows-DiskDiagnosticDataCollector', 'GatherNetworkInfo', 'QueueReporting' + ErrorAction = $SCT + } + $null = (Get-ScheduledTask @paramGetScheduledTask | Disable-ScheduledTask -ErrorAction $SCT) + #endregion DisableTelemetry + + #region DisableWiFiSense + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting\value' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspot\value' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\WcmSvc\wifinetworkmanager\config\AutoConnectAllowedOEM' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\WcmSvc\wifinetworkmanager\config\WiFISenseAllowed' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWiFiSense + + #region DisableWebSearch + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search\DisableWebSearch' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWebSearch + + #region DisableAppSuggestions + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\CloudContent\DisableWindowsConsumerFeatures' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsInkWorkspace\AllowSuggestedAppsInWindowsInkWorkspace' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAppSuggestions + + #region DisableActivityHistory + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System\EnableActivityFeed' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System\PublishUserActivities' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System\UploadUserActivities' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableActivityHistory + + #region HideQuickAccess + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HubMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideQuickAccess + + #region DisableBackgroundApps + $ExcludedApps = @('Microsoft.LockApp*', 'Microsoft.Windows.ContentDeliveryManager*', 'Microsoft.Windows.Cortana*', 'Microsoft.Windows.SecHealthUI*', 'Microsoft.Windows.ShellExperienceHost*', 'Microsoft.Windows.StartMenuExperienceHost*') + $OFS = '|' + $paramGetChildItem = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications' + ErrorAction = $SCT + } + $null = (Get-ChildItem @paramGetChildItem | Where-Object -FilterScript { + $_.PSChildName -cnotmatch $ExcludedApps + } | ForEach-Object -Process { + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + 'Disabled') + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + 'DisabledByUser') + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + }) + $OFS = ' ' + #endregion DisableBackgroundApps + + #region EnableSensors + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\LocationAndSensors' -Name 'DisableSensors' @paramRemoveItemProperty) + #endregion EnableSensors + + #region DisableLocation + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\LocationAndSensors\DisableLocation' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\LocationAndSensors\DisableLocationScripting' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableLocation + + #region DisableMapUpdates + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\Maps\AutoUpdateEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableMapUpdates + + #region DisableFeedback + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection\DoNotShowFeedbackNotifications' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramDisableScheduledTask = @{ + TaskName = 'Microsoft\Windows\Feedback\Siuf\DmClient' + ErrorAction = $SCT + } + $null = (Disable-ScheduledTask @paramDisableScheduledTask) + $paramDisableScheduledTask = @{ + TaskName = 'Microsoft\Windows\Feedback\Siuf\DmClientOnScenarioDownload' + ErrorAction = $SCT + } + $null = (Disable-ScheduledTask @paramDisableScheduledTask) + #endregion DisableFeedback + + #region DisableTailoredExperiences + #endregion DisableTailoredExperiences + + #region DisableAdvertisingID + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\AdvertisingInfo\DisabledByGroupPolicy' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAdvertisingID + + #region DisableWebLangList + #endregion DisableWebLangList + + #region DisableCortana + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search\AllowCortana' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\InputPersonalization\AllowInputPersonalization' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\PolicyManager\default\Experience\AllowCortana\Value' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableCortana + + #region EnableBiometrics + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Biometrics\' -Name 'Enabled' @paramRemoveItemProperty) + #endregion EnableBiometrics + + #region EnableCamera + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Camera' -Name 'AllowCamera' @paramRemoveItemProperty) + #endregion EnableCamera + + #region EnableMicrophone + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\AppPrivacy' -Name 'LetAppsAccessMicrophone' @paramRemoveItemProperty) + #endregion EnableMicrophone + + #region DisableErrorReporting + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\Windows Error Reporting\Disabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $null = (Disable-ScheduledTask -TaskName 'Microsoft\Windows\Windows Error Reporting\QueueReporting') + #endregion DisableErrorReporting + + #region SetP2PUpdateLocal + # TODO: Convert to switch + if ([Environment]::OSVersion.Version.Build -eq 10240) + { + # Method used in 1507 + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config\DODownloadMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + elseif ([Environment]::OSVersion.Version.Build -le 14393) + { + # Method used in 1511 and 1607 + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization\DODownloadMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + else + { + # Method used since 1703 + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeliveryOptimization' -Name 'DODownloadMode' @paramRemoveItemProperty) + } + #endregion SetP2PUpdateLocal + + #region EnableSyncForegroundPolicy + # Always wait for the network at computer startup and logon + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\Winlogon\SyncForegroundPolicy' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableSyncForegroundPolicy + + #region EnableUseOLEDTaskbarTransparency + # Turn on acrylic taskbar transparency + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\UseOLEDTaskbarTransparency' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableUseOLEDTaskbarTransparency + + $paramStopService = @{ + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $paramSetService = @{ + StartupType = 'Disabled' + ErrorAction = $SCT + } + + #region DisableDiagTrack + $paramGetService = @{ + Name = 'DiagTrack' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + #endregion DisableDiagTrack + + #region WMPNetworkSvc + $paramGetService = @{ + Name = 'WMPNetworkSvc' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + #endregion WMPNetworkSvc + + #region DisableContactData + $paramGetService = @{ + Name = 'PimIndexMaintenanceSvc_*' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Services\PimIndexMaintenanceSvc\Start' + PropertyType = 'DWord' + Value = '4' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Services\PimIndexMaintenanceSvc\UserServiceFlags' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableContactData + + #region EnableActiveProbing + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Services\NlaSvc\Parameters\Internet\EnableActiveProbing\EnableActiveProbing' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableActiveProbing + + #region DisableUserDataStorage + $paramGetService = @{ + Name = 'UnistoreSvc_*' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Services\UnistoreSvc\Start' + PropertyType = 'DWord' + Value = '4' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Services\UnistoreSvc\UserServiceFlags' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableUserDataStorage + + #region DisableUserDataAccess + $paramGetService = @{ + Name = 'UserDataSvc_*' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Services\UserDataSvc\Start' + PropertyType = 'DWord' + Value = '4' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Services\UserDataSvc\UserServiceFlags' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableUserDataAccess + + #region StopEventTraceSessions + $paramGetEtwTraceSession = @{ + Name = 'DiagLog' + ErrorAction = $SCT + } + $paramStopEtwTraceSession = @{ + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-EtwTraceSession @paramGetEtwTraceSession | Stop-EtwTraceSession @paramStopEtwTraceSession) + #endregion StopEventTraceSessions + + #region UpdateAutologgerConfig + # Turn off the data collectors at the next computer restart + $null = (Update-AutologgerConfig -Name DiagLog, AutoLogger-Diagtrack-Listener -Start 0 -ErrorAction $SCT) + #endregion UpdateAutologgerConfig + + #region EnableWAPPush + $paramSetService = @{ + Name = 'dmwappushservice' + StartupType = 'Automatic' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-Service @paramSetService) + $paramStartService = @{ + Name = 'dmwappushservice' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Start-Service @paramStartService) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\dmwappushservice\DelayedAutoStart' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableWAPPush + + #region EnableClearRecentFiles + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\ClearRecentDocsOnExit' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableClearRecentFiles + + #region DisableRecentFiles + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoRecentDocsHistory' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableRecentFiles + #endregion PrivacyTweaks + + #region SecurityTweaks + #region SetUACHigh + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ConsentPromptBehaviorAdmin' + PropertyType = 'DWord' + Value = '5' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\PromptOnSecureDesktop' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetUACHigh + + #region EnableSharingMappedDrives + # Turn on access to mapped drives from app running with elevated permissions with Admin Approval Mode enabled + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableLinkedConnections' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableSharingMappedDrives + + #region EnableAdminShares + $null = (Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters' -Name 'AutoShareWks' @paramRemoveItemProperty) + #endregion EnableAdminShares + + #region EnableFirewall + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsFirewall\StandardProfile' -Name 'EnableFirewall' @paramRemoveItemProperty) + #endregion EnableFirewall + + #region ShowDefenderTrayIcon + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender Security Center\Systray' -Name 'HideSystray' @paramRemoveItemProperty) + + # TODO: Convert to switch + if ([Environment]::OSVersion.Version.Build -eq 14393) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\WindowsDefender' + PropertyType = 'ExpandString' + Value = "`"%ProgramFiles%\Windows Defender\MSASCuiL.exe`"" + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + elseif ([Environment]::OSVersion.Version.Build -ge 15063 -And [Environment]::OSVersion.Version.Build -le 17134) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\SecurityHealth' + PropertyType = 'ExpandString' + Value = '%ProgramFiles%\Windows Defender\MSASCuiL.exe' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + elseif ([Environment]::OSVersion.Version.Build -ge 17763) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\SecurityHealth' + PropertyType = 'ExpandString' + Value = '%windir%\system32\SecurityHealthSystray.exe' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + #endregion ShowDefenderTrayIcon + + #region EnableDefender + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender' -Name 'DisableAntiSpyware' @paramRemoveItemProperty) + + # TODO: Convert to switch + if ([Environment]::OSVersion.Version.Build -eq 14393) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\WindowsDefender' + PropertyType = 'ExpandString' + Value = "`"%ProgramFiles%\Windows Defender\MSASCuiL.exe`"" + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + elseif ([Environment]::OSVersion.Version.Build -ge 15063 -And [Environment]::OSVersion.Version.Build -le 17134) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\SecurityHealth' + PropertyType = 'ExpandString' + Value = '%ProgramFiles%\Windows Defender\MSASCuiL.exe' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + elseif ([Environment]::OSVersion.Version.Build -ge 17763) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run\SecurityHealth' + PropertyType = 'ExpandString' + Value = '%windir%\system32\SecurityHealthSystray.exe' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + #endregion EnableDefender + + #region EnableDefenderCloud + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender\Spynet' -Name 'SpynetReporting' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows Defender\Spynet' -Name 'SubmitSamplesConsent' @paramRemoveItemProperty) + #endregion EnableDefenderCloud + + #region EnableControlledFolderAccess + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -ErrorAction $SCT) + #endregion EnableControlledFolderAccess + + #region EnableCoreIsolationMemoryIntegrity + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\DeviceGuard\Scenarios\HypervisorEnforcedCodeIntegrity\Enabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableCoreIsolationMemoryIntegrity + + #region EnableDefenderApplicationGuard + $paramEnableWindowsOptionalFeature = @{ + Online = $true + FeatureName = 'Windows-Defender-ApplicationGuard' + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-WindowsOptionalFeature @paramEnableWindowsOptionalFeature) + #endregion EnableDefenderApplicationGuard + + #region EnableDotNetStrongCrypto + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\.NETFramework\v4.0.30319\SchUseStrongCrypto' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\v4.0.30319\SchUseStrongCrypto' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableDotNetStrongCrypto + + #region DisableF8BootMenu + $null = (& "$env:windir\system32\bcdedit.exe" /set `{current`} BootMenuPolicy Standard) + #endregion DisableF8BootMenu + + #region DisableBootRecovery + $null = (& "$env:windir\system32\bcdedit.exe" /set `{current`} BootStatusPolicy IgnoreAllFailures) + #endregion DisableBootRecovery + + #region SetDEPOptIn + $null = (& "$env:windir\system32\bcdedit.exe" /set `{current`} nx OptIn) + #endregion SetDEPOptIn + #endregion SecurityTweaks + + #region NetworkTweaks + #region SetUnknownNetworksPublic + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\CurrentVersion\NetworkList\Signatures\010103000F0000F0010000000F0000F0C967A3643C3AD745950DA7859209176EF5B87C875FA20DF21951640E807D7C24' -Name 'Category' @paramRemoveItemProperty) + #endregion SetUnknownNetworksPublic + + #region DisableNetDevicesAutoInstallation + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\NcdAutoSetup\Private\AutoSetup' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableNetDevicesAutoInstallation + + #region DisableHomeGroups + $paramStopService = @{ + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $paramSetService = @{ + StartupType = 'Disabled' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + + $paramGetService = @{ + Name = 'HomeGroupListener' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + + $paramGetService = @{ + Name = 'HomeGroupProvider' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + #endregion DisableHomeGroups + + #region DisableSMB1Protocol + $paramSetSmbServerConfiguration = @{ + EnableSMB1Protocol = $false + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-SmbServerConfiguration @paramSetSmbServerConfiguration) + #endregion DisableSMB1Protocol + + #region DisableSMB1Server + $paramSetSmbServerConfiguration = @{ + EnableSMB1Protocol = $false + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-SmbServerConfiguration @paramSetSmbServerConfiguration) + #endregion DisableSMB1Server + + #region DisableNetBIOSOverTCP + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\services\NetBT\Parameters\Interfaces\Tcpip*\NetbiosOptions' + PropertyType = 'DWord' + Value = 2 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableNetBIOSOverTCP + + #region DisableLLMNR + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows NT\DNSClient\EnableMulticast' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableLLMNR + + #region DisableLLDP + $paramDisableNetAdapterBinding = @{ + Name = '*' + ComponentID = 'ms_lldp' + WarningAction = $SCT + ErrorAction = $SCT + } + + $null = (Disable-NetAdapterBinding @paramDisableNetAdapterBinding) + #endregion DisableLLDP + + #region DisableLLTD + $paramDisableNetAdapterBinding = @{ + Name = '*' + ComponentID = 'ms_lltdio' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Disable-NetAdapterBinding @paramDisableNetAdapterBinding) + + $paramDisableNetAdapterBinding = @{ + Name = '*' + ComponentID = 'ms_rspndr' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Disable-NetAdapterBinding @paramDisableNetAdapterBinding) + #endregion DisableLLTD + + #region EnableQoS + $paramEnableNetAdapterBinding = @{ + Name = '*' + ComponentID = 'ms_pacer' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-NetAdapterBinding @paramEnableNetAdapterBinding) + #endregion EnableQoS + + #region EnableIPv4Stack + $paramEnableNetAdapterBinding = @{ + Name = '*' + ComponentID = 'ms_tcpip' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-NetAdapterBinding @paramEnableNetAdapterBinding) + #endregion EnableIPv4Stack + + #region EnableIPv6Stack + $paramEnableNetAdapterBinding = @{ + Name = '*' + ComponentID = 'ms_tcpip6' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-NetAdapterBinding @paramEnableNetAdapterBinding) + #endregion EnableIPv6Stack + + #region DisableNCSIProbe + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\NetworkConnectivityStatusIndicator\NoActiveProbe' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableNCSIProbe + + #region DisableConnectionSharing + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Network Connections\NC_ShowSharedAccessUI' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableConnectionSharing + + #region DisableRemoteAssistance + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Remote Assistance\fAllowToGetHelp' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableRemoteAssistance + + #region EnableRemoteDesktop + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\fDenyTSConnections' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramEnableNetFirewallRule = @{ + Name = 'RemoteDesktop*' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-NetFirewallRule @paramEnableNetFirewallRule) + #endregion EnableRemoteDesktop + #endregion NetworkTweaks + + #region ServiceTweaks + #region DisableApplicationCompatibilityEngine + # Disable Application Compatibility Engine and Program Compatibility Assistant + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Policies\Microsoft\Windows\AppCompat\DisableEngine' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableApplicationCompatibilityEngine + + #region DisableProgramCompatibilityAssistant + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Policies\Microsoft\Windows\AppCompat\DisablePCA' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableProgramCompatibilityAssistant + + #region EnableUpdateMSRT + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\MRT' -Name 'DontOfferThroughWUAU' @paramRemoveItemProperty) + #endregion EnableUpdateMSRT + + #region EnableUpdateDriver + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata' -Name 'PreventDeviceMetadataFromNetwork' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching' -Name 'DontPromptForWindowsUpdate' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching' -Name 'DontSearchWindowsUpdate' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching' -Name 'DriverUpdateWizardWuSearchEnabled' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate' -Name 'ExcludeWUDriversInQualityUpdate' @paramRemoveItemProperty) + #endregion EnableUpdateDriver + + #region EnableUpdateMSProducts + $paramNewObject = @{ + ComObject = 'Microsoft.Update.ServiceManager' + } + + $null = (New-Object @paramNewObject).AddService2('7971f918-a847-4430-9279-4a52d1efe18d', 7, '') + #endregion EnableUpdateMSProducts + + #region DisableUpdateAutoDownload + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\AUOptions' + PropertyType = 'DWord' + Value = 2 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableUpdateAutoDownload + + #region EnableUpdateRestart + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\MusNotification.exe' -Name 'Debugger' @paramRemoveItemProperty) + #endregion EnableUpdateRestart + + #region DisableMaintenanceWakeUp + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU\AUPowerManagement' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\Maintenance\WakeUp' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableMaintenanceWakeUp + + #region DisableAutoRestartSignOn + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\DisableAutomaticRestartSignOn' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAutoRestartSignOn + + #region DisableAutorun + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoDriveTypeAutoRun' + PropertyType = 'DWord' + Value = 255 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAutorun + + #region EnableRestorePoints + $paramEnableComputerRestore = @{ + Drive = ($env:SYSTEMDRIVE) + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-ComputerRestore @paramEnableComputerRestore) + #endregion EnableRestorePoints + + #region DisableDefragmentation + $paramDisableScheduledTask = @{ + TaskName = 'Microsoft\Windows\Defrag\ScheduledDefrag' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Disable-ScheduledTask @paramDisableScheduledTask) + #endregion DisableDefragmentation + + #region DisableSuperfetch + $paramGetService = @{ + Name = 'SysMain' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramStopService = @{ + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $paramSetService = @{ + StartupType = 'Disabled' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Stop-Service @paramStopService) + $null = (Get-Service @paramGetService | Set-Service @paramSetService) + #endregion DisableSuperfetch + + #region EnableIndexing + $paramSetService = @{ + Name = 'WSearch' + StartupType = 'Automatic' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-Service @paramSetService) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Services\WSearch\DelayedAutoStart' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableIndexing + + #region EnableSwapFile + $null = (Remove-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management' -Name 'SwapfileControl' @paramRemoveItemProperty) + #endregion EnableSwapFile + + #region EnableNTFSLongPaths + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableNTFSLongPaths + + #region GroupSvchostProcesses + # Group svchost.exe processes + $paramGetCimInstance = @{ + ClassName = 'Win32_PhysicalMemory' + WarningAction = $SCT + ErrorAction = $SCT + } + $ram = ((Get-CimInstance @paramGetCimInstance | Measure-Object -Property 'Capacity' -Sum).Sum / 1kb) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\SvcHostSplitThresholdInKB' + PropertyType = 'DWord' + Value = $ram + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion GroupSvchostProcesses + + #region EnableDisplayParameters + # Display the Stop error information on the BSoD + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Control\CrashControl\DisplayParameters' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableDisplayParameters + + #region EnableSaveZoneInformation + # Do not preserve zone information + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Attachments\SaveZoneInformation' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableSaveZoneInformation + + #region DisableNTFSLastAccess + $null = (& "$env:windir\system32\fsutil.exe" behavior set DisableLastAccess 1) + #endregion DisableNTFSLastAccess + + #region SetBIOSTimeUTC + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\RealTimeIsUniversal' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetBIOSTimeUTC + + #region DisableFastStartup + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power\HiberbootEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableFastStartup + + #region EnableAutoRebootOnCrash + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\CrashControl\AutoReboot' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableAutoRebootOnCrash + #endregion ServiceTweaks + + #region UITweaks + #region DisableLockScreen + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Personalization\NoLockScreen' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $service = (New-Object -ComObject Schedule.Service) + $service.Connect() + $task = $service.NewTask(0) + $task.Settings.DisallowStartIfOnBatteries = $false + $trigger = $task.Triggers.Create(9) + $trigger = $task.Triggers.Create(11) + $trigger.StateChange = 8 + $action = $task.Actions.Create(0) + $action.Path = 'reg.exe' + $action.Arguments = 'add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\SessionData /t REG_DWORD /v AllowLockScreen /d 0 /f' + $null = ($service.GetFolder('\').RegisterTaskDefinition('Disable LockScreen', $task, 6, 'NT AUTHORITY\SYSTEM', $null, 4)) + #endregion DisableLockScreen + + #region AwayModeEnabled + # Lock screen (not sleep) on lid close + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power\AwayModeEnabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion AwayModeEnabled + + #region HideNetworkFromLockScreen + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System\DontDisplayNetworkSelectionUI' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideNetworkFromLockScreen + + #region ShowShutdownOnLockScreen + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\ShutdownWithoutLogon' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowShutdownOnLockScreen + + #region DisableLockScreenBlur + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\System\DisableAcrylicBackgroundOnLogon' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableLockScreenBlur + + #region DisableSearchAppInStore + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer\NoUseStoreOpenWith' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableSearchAppInStore + + #region DisableNewAppPrompt + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer\NoNewAppAlert' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableNewAppPrompt + + #region HideRecentlyAddedApps + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer\HideRecentlyAddedApps' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideRecentlyAddedApps + + #region HideMostUsedApps + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer\NoStartMenuMFUprogramsList' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramNewItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer' + Name = 'NoStartMenuMFUprogramsList' + PropertyType = 'DWord' + Value = 1 + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + + $paramSetItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer' + Name = 'NoStartMenuMFUprogramsList' + Value = 1 + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + #endregion HideMostUsedApps + + #region ShowShortcutArrow + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Icons' -Name '29' @paramRemoveItemProperty) + #endregion ShowShortcutArrow + + #region RemoveENKeyboard + $paramGetWinUserLanguageList = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $langs = (Get-WinUserLanguageList @paramGetWinUserLanguageList) + + if ($langs) + { + $paramSetWinUserLanguageList = @{ + LanguageList = ($langs | Where-Object { + $_.LanguageTag -ne 'en-US' + }) + Force = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Set-WinUserLanguageList @paramSetWinUserLanguageList) + } + #endregion RemoveENKeyboard + + #region DisableStartupSound + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI\BootAnimation\DisableStartupSound' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableStartupSound + + #region EnableChangingSoundScheme + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Personalization' -Name 'NoChangingSoundScheme' @paramRemoveItemProperty) + #endregion EnableChangingSoundScheme + + #region DisableVerboseStatus + $paramGetCimInstance = @{ + ClassName = 'Win32_OperatingSystem' + WarningAction = $SCT + ErrorAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).ProductType -eq 1) + { + $null = (Remove-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System' -Name 'VerboseStatus' @paramRemoveItemProperty) + } + else + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System\VerboseStatus' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + #endregion DisableVerboseStatus + #endregion UITweaks + + #region ExplorerUITweaks + #region HideDesktopFromThisPC + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}' -Recurse @paramRemoveItemProperty) + #endregion HideDesktopFromThisPC + + #region HideDesktopFromExplorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideDesktopFromExplorer + + #region HideDocumentsFromThisPC + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{d3162b92-9365-467a-956b-92703aca08af}' -Recurse @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{A8CDFF1C-4878-43be-B5FD-F8091C1C60D0}' -Recurse @paramRemoveItemProperty) + #endregion HideDocumentsFromThisPC + + #region HideDocumentsFromExplorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{f42ee2d3-909f-4907-8871-4c22fc0bf756}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{f42ee2d3-909f-4907-8871-4c22fc0bf756}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideDocumentsFromExplorer + + #region HideDownloadsFromThisPC + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{088e3905-0323-4b02-9826-5d99428e115f}' -Recurse @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{374DE290-123F-4565-9164-39C4925E467B}' -Recurse @paramRemoveItemProperty) + #endregion HideDownloadsFromThisPC + + #region HideDownloadsFromExplorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{7d83ee9b-2244-4e70-b1f5-5393042af1e4}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{7d83ee9b-2244-4e70-b1f5-5393042af1e4}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideDownloadsFromExplorer + + #region HideMusicFromThisPC + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}' -Recurse @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}' -Recurse @paramRemoveItemProperty) + #endregion HideMusicFromThisPC + + #region HideMusicFromExplorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{a0c69a99-21c8-4671-8703-7934162fcf1d}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{a0c69a99-21c8-4671-8703-7934162fcf1d}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideMusicFromExplorer + + #region HidePicturesFromThisPC + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}' -Recurse @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}' -Recurse @paramRemoveItemProperty) + #endregion HidePicturesFromThisPC + + #region HidePicturesFromExplorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{0ddd015d-b06c-45d5-8c4c-f59713854639}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{0ddd015d-b06c-45d5-8c4c-f59713854639}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HidePicturesFromExplorer + + #region HideVideosFromThisPC + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}' -Recurse @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{A0953C92-50DC-43bf-BE83-3742FED03C9C}' -Recurse @paramRemoveItemProperty) + #endregion HideVideosFromThisPC + + #region HideVideosFromExplorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{35286a68-3c57-41a1-bbb1-0eae73d76c95}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{35286a68-3c57-41a1-bbb1-0eae73d76c95}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideVideosFromExplorer + + #region Hide3DObjectsFromThisPC + $null = (Remove-Item -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{0DB7E03F-FC29-4DC6-9020-FF41B59E513A}' -Recurse @paramRemoveItemProperty) + #endregion Hide3DObjectsFromThisPC + + #region Hide3DObjectsFromExplorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{31C0DD25-9439-4F12-BF41-7FF4EDA38722}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer\FolderDescriptions\{31C0DD25-9439-4F12-BF41-7FF4EDA38722}\PropertyBag\ThisPCPolicy' + PropertyType = 'String' + Value = 'Hide' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion Hide3DObjectsFromExplorer + + #region HideIncludeInLibraryMenu + $paramTestPath = @{ + Path = 'HKCR:' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewPSDrive = @{ + Name = 'HKCR' + PSProvider = 'Registry' + Root = 'HKEY_CLASSES_ROOT' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-PSDrive @paramNewPSDrive) + } + + $null = (Remove-Item -Path 'HKCR:\Folder\ShellEx\ContextMenuHandlers\Library Location' @paramRemoveItemProperty) + #endregion HideIncludeInLibraryMenu + + #region HideGiveAccessToMenu + $paramTestPath = @{ + Path = 'HKCR:' + WarningAction = $SCT + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewPSDrive = @{ + Name = 'HKCR' + PSProvider = 'Registry' + Root = 'HKEY_CLASSES_ROOT' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-PSDrive @paramNewPSDrive) + } + + $null = (Remove-Item -LiteralPath 'HKCR:\*\shellex\ContextMenuHandlers\Sharing' @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKCR:\Directory\Background\shellex\ContextMenuHandlers\Sharing' @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKCR:\Directory\shellex\ContextMenuHandlers\Sharing' @paramRemoveItemProperty) + $null = (Remove-Item -Path 'HKCR:\Drive\shellex\ContextMenuHandlers\Sharing' @paramRemoveItemProperty) + #endregion HideGiveAccessToMenu + + #region RemoveHPSupportAssistantShortcut + $null = (Remove-Item -Path ($env:PUBLIC + '\Desktop\HP Support Assistant.lnk') -Force -ErrorAction $SCT) + #endregion RemoveHPSupportAssistantShortcut + #endregion ExplorerUITweaks + + #region Application Tweaks + #region ConfigureMakeMeAdmin + # Plase see: https://makemeadmin.org/registry-settings.html + + # Create "Make Me Admin" Sub-Tree + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin' + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # List of SIDs or names for users or groups that are allowed to obtain administrator rights on the local machine. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Allowed Entities' + PropertyType = 'MultiString' + Value = 'S-1-12-1-2855414155-1143912517-1469153414-3894389289' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # List of SIDs or names for users or groups that are not allowed to obtain administrator rights on the local machine. Denials take precedence over allowed entities. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Denied Entities' + PropertyType = 'MultiString' + Value = 'S-1-12-1-4187981707-1270255834-494492805-1262097559' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # List of SIDs or names for users or groups that are automatically added to the Administrators group upon logon. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Automatic Add Allowed' + PropertyType = 'MultiString' + Value = 'S-1-12-1-625767786-1256204928-461728438-4204344446 S-1-12-1-3524765092-1083350200-2707824802-249986053' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # List of SIDs or names for users or groups that are never allowed to be added automatically to the Administrators group upon logon. Denials take precedence over allowed entities. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Automatic Add Denied' + PropertyType = 'MultiString' + Value = 'S-1-12-1-3644612835-1324734094-3927402880-3336220471 S-1-12-1-755265717-1106991458-2990996133-1768637124' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # List of SIDs or names for users or groups that are allowed to obtain administrator rights from a remote computer. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Remote Allowed Entities' + PropertyType = 'MultiString' + Value = 'S-1-12-1-625767786-1256204928-461728438-4204344446 S-1-12-1-3524765092-1083350200-2707824802-249986053' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # List of SIDs or names for users or groups that are not allowed to obtain administrator rights from a remote computer. Denials take precedence over allowed entities. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Remote Denied Entities' + PropertyType = 'MultiString' + Value = 'S-1-12-1-4187981707-1270255834-494492805-1262097559 S-1-12-1-3644612835-1324734094-3927402880-3336220471 S-1-12-1-755265717-1106991458-2990996133-1768637124' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Specifies different timeout values for users or groups. For example, you can allow your help desk 60 minutes while allowing everyone else 15 minutes. The highest timeout value that applies to a given user wins. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Timeout Overrides' + PropertyType = 'String' + Value = '' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # The default number of minutes that the user will be added to the Administrators group. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Admin Rights Timeout' + PropertyType = 'DWord' + Value = '10' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Specifies whether to remove administrator rights if a user logs off of their Windows session. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Remove Admin Rights On Logout' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Specifies whether to re-add a user to the Administrators group, if they are removed by another process, e.g., a Group Policy refresh. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Override Removal By Outside Process' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Specifies whether to allow requests for administrator rights from remote computers. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\Allow Remote Requests' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Specifies whether remote sessions are terminated when the user's administrator rights expire. + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Sinclair Community College\Make Me Admin\End Remote Sessions Upon Expiration' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ConfigureMakeMeAdmin + + #region + # Edge related + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Edge\HideFirstRunExperience' + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + $paramNewItem = @{ + Path = 'HKLM:\\SOFTWARE\Policies\Microsoft\MicrosoftEdge\Main' + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Remove Edge icon on desktop + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DisableEdgeDesktopShortcutCreation' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Show the initial setup ? + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Edge\HideFirstRunExperience' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Do NOT allow Microsoft Edge to pre-launch at Windows startup, when the system is idle, and each time Microsoft Edge is closed + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Policies\Microsoft\MicrosoftEdge\Main\AllowPrelaunch' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # No preloading of the startpage and Tabs + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Policies\Microsoft\MicrosoftEdge\Main\TabPreloader' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Configure Do Not Track + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Policies\Microsoft\MicrosoftEdge\Main\DoNotTrack' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Show message when opening sites in Internet Explorer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Policies\Microsoft\MicrosoftEdge\Main\ShowMessageWhenOpeningSitesInInternetExplorer' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region EnableOneDrive + if (-not ($env:COMPUTERNAME -match 'ENSHARED-')) + { + $null = (Remove-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\OneDrive' -Name 'DisableFileSyncNGSC' @paramRemoveItemProperty) + } + endregion EnableOneDrive + + #region InstallWindowsStore + $paramGetAppxPackage = @{ + AllUsers = $true + Name = 'Microsoft.DesktopAppInstaller' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-AppxPackage @paramGetAppxPackage | ForEach-Object { + $paramAddAppxPackage = @{ + DisableDevelopmentMode = $true + Register = $true + Path = ($_.InstallLocation + '\AppXManifest.xml') + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Add-AppxPackage @paramAddAppxPackage) + }) + + $paramGetAppxPackage = @{ + AllUsers = $true + Name = 'Microsoft.Services.Store.Engagement' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-AppxPackage @paramGetAppxPackage | ForEach-Object { + $paramAddAppxPackage = @{ + DisableDevelopmentMode = $true + Register = $true + Path = ($_.InstallLocation + '\AppXManifest.xml') + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Add-AppxPackage @paramAddAppxPackage) + }) + + $paramGetAppxPackage = @{ + AllUsers = $true + Name = 'Microsoft.StorePurchaseApp' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-AppxPackage @paramGetAppxPackage | ForEach-Object { + $paramAddAppxPackage = @{ + DisableDevelopmentMode = $true + Register = $true + Path = ($_.InstallLocation + '\AppXManifest.xml') + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Add-AppxPackage @paramAddAppxPackage) + }) + + $paramGetAppxPackage = @{ + AllUsers = $true + Name = 'Microsoft.WindowsStore' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-AppxPackage @paramGetAppxPackage | ForEach-Object { + $paramAddAppxPackage = @{ + DisableDevelopmentMode = $true + Register = $true + Path = ($_.InstallLocation + '\AppXManifest.xml') + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Add-AppxPackage @paramAddAppxPackage) + }) + #endregion InstallWindowsStore + + #region DisableAdobeFlash + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Internet Explorer\DisableFlashInIE' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdge\Addons\FlashPlayerEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAdobeFlash + + #region DisableEdgePreload + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdge\Main\AllowPrelaunch' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\MicrosoftEdge\TabPreloader\AllowTabPreloading' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableEdgePreload + + #region DisableEdgeShortcutCreation + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DisableEdgeDesktopShortcutCreation' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableEdgeShortcutCreation + + + if (-not ($env:COMPUTERNAME -match 'ENSHARED-')) + { + #region ConfiguteOneDrive + # Try Auto configure + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\OneDrive\SilentAccountConfig' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Enable the FilesOnDemand Freature + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\OneDrive\FilesOnDemandEnabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ConfiguteOneDrive + } + + #region DisableIEFirstRun + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Internet Explorer\Main\DisableFirstRunCustomize' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableIEFirstRun + + #region DisableFirstLogonAnimation + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\EnableFirstLogonAnimation' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableFirstLogonAnimation + + #region RestartNotificationsAllowed2 + # Show more Windows Update restart notifications about restarting + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings\RestartNotificationsAllowed2' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion RestartNotificationsAllowed2 + + #region + # Automatically adjust active hours for me based on daily usage + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings\SmartActiveHoursState' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region DisableMediaSharing + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\WindowsMediaPlayer\PreventLibrarySharing' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableMediaSharing + + #region UninstallWorkFolders + $paramGetWindowsOptionalFeature = @{ + Online = $true + FeatureName = 'WorkFolders-Client' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramDisableWindowsOptionalFeature = @{ + Online = $true + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsOptionalFeature @paramGetWindowsOptionalFeature | Where-Object { + $_.State -ne 'Disabled' + } | Disable-WindowsOptionalFeature @paramDisableWindowsOptionalFeature) + #endregion UninstallWorkFolders + + #region UninstallPowerShellV2 + $paramGetWindowsOptionalFeature = @{ + Online = $true + FeatureName = 'MicrosoftWindowsPowerShellV2Root' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsOptionalFeature @paramGetWindowsOptionalFeature | Where-Object { + $_.State -ne 'Disabled' + } | Disable-WindowsOptionalFeature @paramDisableWindowsOptionalFeature) + #endregion UninstallPowerShellV2 + + #region InstallSSHClient + $paramGetWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $paramAddWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsCapability @paramGetWindowsCapability | Where-Object { + (($_.Name -like 'OpenSSH.Client*') -and ($_.State -eq 'NotPresent')) + } | Add-WindowsCapability @paramAddWindowsCapability) + #endregion InstallSSHClient + + #region UninstallSSHServer + $paramStopService = @{ + Name = 'sshd' + Force = $true + NoWait = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Stop-Service @paramStopService) + + $paramGetWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $paramRemoveWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsCapability @paramGetWindowsCapability | Where-Object { + (($_.Name -like 'OpenSSH.Server*') -and ($_.State -eq 'Installed')) + } | Remove-WindowsCapability @paramRemoveWindowsCapability) + #endregion UninstallSSHServer + + #region SetPhotoViewerAssociation + $paramTestPath = @{ + Path = 'HKCR:' + WarningAction = $SCT + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewPSDrive = @{ + Name = 'HKCR' + PSProvider = 'Registry' + Root = 'HKEY_CLASSES_ROOT' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-PSDrive @paramNewPSDrive) + } + + foreach ($type in @('Paint.Picture', 'giffile', 'jpegfile', 'pngfile')) + { + $paramNewItem = @{ + Path = ('HKCR:\' + $type + '\shell\open') + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + $paramNewItem = @{ + Path = ('HKCR:\' + $type + '\shell\open\command') + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + $paramConfirmRegistryItemProperty = @{ + Path = ('HKCR:\' + $type + '\shell\open\MuiVerb') + PropertyType = 'ExpandString' + Value = '@%ProgramFiles%\Windows Photo Viewer\photoviewer.dll,-3043' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = ('HKCR:\' + $type + '\shell\open\command\(Default)') + PropertyType = 'ExpandString' + Value = "%SystemRoot%\System32\rundll32.exe `"%ProgramFiles%\Windows Photo Viewer\PhotoViewer.dll`", ImageView_Fullscreen %1" + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + #endregion SetPhotoViewerAssociation + + #region AddPhotoViewerOpenWith + $paramTestPath = @{ + Path = 'HKCR:' + WarningAction = $SCT + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewPSDrive = @{ + Name = 'HKCR' + PSProvider = 'Registry' + Root = 'HKEY_CLASSES_ROOT' + Confirm = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-PSDrive @paramNewPSDrive) + } + + $paramNewItem = @{ + Path = 'HKCR:\Applications\photoviewer.dll\shell\open\command' + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + $paramNewItem = @{ + Path = 'HKCR:\Applications\photoviewer.dll\shell\open\DropTarget' + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCR:\Applications\photoviewer.dll\shell\open\MuiVerb' + PropertyType = 'String' + Value = '@photoviewer.dll,-3043' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCR:\Applications\photoviewer.dll\shell\open\command\(Default)' + PropertyType = 'ExpandString' + Value = "%SystemRoot%\System32\rundll32.exe `"%ProgramFiles%\Windows Photo Viewer\PhotoViewer.dll`", ImageView_Fullscreen %1" + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCR:\Applications\photoviewer.dll\shell\open\DropTarget\Clsid' + PropertyType = 'String' + Value = '{FFE2A43C-56B9-4bf5-9A79-CC6D4285608A}' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion AddPhotoViewerOpenWith + + #region InstallPDFPrinter + $paramDisableWindowsOptionalFeature = @{ + Online = $true + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + + + $paramGetWindowsOptionalFeature = @{ + Online = $true + FeatureName = 'Printing-PrintToPDFServices-Features' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsOptionalFeature @paramGetWindowsOptionalFeature | Where-Object { + $_.State -ne 'Disabled' + } | Disable-WindowsOptionalFeature @paramDisableWindowsOptionalFeature) + #endregion InstallPDFPrinter + + #region UninstallXPSPrinter + $paramGetWindowsOptionalFeature = @{ + Online = $true + FeatureName = 'Printing-XPSServices-Features' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsOptionalFeature @paramGetWindowsOptionalFeature | Where-Object { + $_.State -ne 'Disabled' + } | Disable-WindowsOptionalFeature @paramDisableWindowsOptionalFeature) + #endregion UninstallXPSPrinter + + #region RemoveFaxPrinter + $paramRemovePrinter = @{ + Name = 'Fax' + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-Printer @paramRemovePrinter) + #endregion RemoveFaxPrinter + + #region UninstallFaxAndScan + $paramGetWindowsOptionalFeature = @{ + Online = $true + FeatureName = 'FaxServicesClientPackage' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsOptionalFeature @paramGetWindowsOptionalFeature | Where-Object { + $_.State -ne 'Disabled' + } | Disable-WindowsOptionalFeature @paramDisableWindowsOptionalFeature) + #endregion UninstallFaxAndScan + + #region InstallNET23 + $paramGetCimInstance = @{ + ClassName = 'Win32_OperatingSystem' + ErrorAction = $SCT + WarningAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).ProductType -eq 1) + { + $paramEnableWindowsOptionalFeature = @{ + Online = $true + FeatureName = 'NetFx3' + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-WindowsOptionalFeature @paramEnableWindowsOptionalFeature) + } + #endregion InstallNET23 + #endregion Application Tweaks + + #region + #region RemoveShadowCopies + # Remove Shadow copies (restoration points) + $paramGetCimInstance = @{ + ClassName = 'Win32_ShadowCopy' + WarningAction = $SCT + ErrorAction = $SCT + } + $paramRemoveCimInstance = @{ + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-CimInstance @paramGetCimInstance | Remove-CimInstance @paramRemoveCimInstance) + #endregion RemoveShadowCopies + + #region SystemRestoreCheckpointCreation + # Revert the System Restore checkpoint creation frequency to 1440 minutes + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRestore\SystemRestorePointCreationFrequency' + PropertyType = 'DWord' + Value = '1440' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SystemRestoreCheckpointCreation + + #region + # Turn on latest installed .NET runtime for all apps + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\.NETFramework\OnlyUseLatestCLR' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\OnlyUseLatestCLR' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Do not allow the computer (if device is not a laptop) to turn off all the network adapters to save power + $paramGetCimInstance = @{ + ClassName = 'Win32_ComputerSystem' + WarningAction = $SCT + ErrorAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).PCSystemType -ne 2) + { + $paramGetNetAdapter = @{ + Physical = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $paramGetNetAdapterPowerManagement = @{ + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-NetAdapter @paramGetNetAdapter | Get-NetAdapterPowerManagement @paramGetNetAdapterPowerManagement | Where-Object -FilterScript { + $_.AllowComputerToTurnOffDevice -ne 'Unsupported' + }) | ForEach-Object -Process { + $_.AllowComputerToTurnOffDevice = 'Disabled' + $paramSetNetAdapterPowerManagement = @{ + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = ($_ | Set-NetAdapterPowerManagement @paramSetNetAdapterPowerManagement) + } + } + #endregion + + #region + $paramGetWindowsEdition = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-WindowsEdition @paramGetWindowsEdition | Where-Object -FilterScript { + $_.Edition -eq 'Professional' -or $_.Edition -eq 'Enterprise' + }) + { + $paramGetCimInstance = @{ + ClassName = 'CIM_Processor' + WarningAction = $SCT + ErrorAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).VirtualizationFirmwareEnabled -eq $true) + { + $paramEnableWindowsOptionalFeature = @{ + FeatureName = 'Containers-DisposableClientVM' + All = $true + Online = $true + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-WindowsOptionalFeature @paramEnableWindowsOptionalFeature) + } + else + { + $paramGetCimInstance = @{ + ClassName = 'CIM_ComputerSystem' + WarningAction = $SCT + ErrorAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).HypervisorPresent -eq $true) + { + $paramEnableWindowsOptionalFeature = @{ + FeatureName = 'Containers-DisposableClientVM' + All = $true + Online = $true + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Enable-WindowsOptionalFeature @paramEnableWindowsOptionalFeature) + } + } + } + #endregion + + #region + # Turn off and delete reserved storage after the next update installation + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager\BaseHardReserveSize' + PropertyType = 'QWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager\BaseSoftReserveSize' + PropertyType = 'QWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager\HardReserveAdjustment' + PropertyType = 'QWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager\MinDiskSize' + PropertyType = 'QWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager\ShippedWithReserves' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramGetCommand = @{ + Name = 'Set-WindowsReservedStorageState' + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramSetWindowsReservedStorageState = @{ + State = 'Disabled' + ErrorAction = $SCT + } + $null = (Set-WindowsReservedStorageState @paramSetWindowsReservedStorageState) + } + #endregion + + #region + # Turn on automatic backup the system registry to the $env:SystemRoot\System32\config\RegBack folder + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Configuration Manager\EnablePeriodicBackup' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Turn off thumbnail cache removal + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Thumbnail Cache\Autorun' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\Thumbnail Cache\Autorun' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Use Unicode UTF-8 for worldwide language support + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage\ACP' + PropertyType = 'String' + Value = '65001' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage\MACCP' + PropertyType = 'String' + Value = '65001' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\Nls\CodePage\OEMCP' + PropertyType = 'String' + Value = '65001' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Do not show recently added apps on Start menu + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Explorer\CHideRecentlyAddedApps' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Turn on logging for all Windows PowerShell modules + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames\*' + PropertyType = 'String' + Value = '*' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames\EnableModuleLogging' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging\EnableScriptBlockLogging' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Include command line in progress creation events + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit\ProcessCreationIncludeCmdLine_Enabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Remove "Edit with Paint 3D" from context menu + $exts = @('.bmp', '.gif', '.jpe', '.jpeg', '.jpg', '.png', '.tif', '.tiff') + + foreach ($ext in $exts) + { + $null = (Remove-Item -Path ('Registry::HKEY_CLASSES_ROOT\SystemFileAssociations\' + $ext + '\Shell\3D Edit\ProgrammaticAccessOnly') @paramRemoveItemProperty) + } + #endregion + + #region + # Remove "Include in Library" from context menu + $paramConfirmRegistryItemProperty = @{ + Path = 'Registry::HKEY_CLASSES_ROOT\Folder\shellex\ContextMenuHandlers\Library Location\(default)' + PropertyType = 'String' + Value = '-{3dad6c5d-2167-4cae-9914-f99e41c12cfa}' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Remove "Edit with Photos" from context menu + $null = (Remove-Item -Path 'Registry::HKEY_CLASSES_ROOT\AppX43hnxtbyyps62jhe9sqpdzxn1790zetc\Shell\ShellEdit\ProgrammaticAccessOnly' @paramRemoveItemProperty) + + # Remove "Create a new video" from context menu + $null = (Remove-Item -Path 'Registry::HKEY_CLASSES_ROOT\AppX43hnxtbyyps62jhe9sqpdzxn1790zetc\Shell\ShellCreateVideo\ProgrammaticAccessOnly' @paramRemoveItemProperty) + + # Remove "Edit" from images context menu + $null = (Remove-Item -Path 'Registry::HKEY_CLASSES_ROOT\SystemFileAssociations\image\shell\edit\ProgrammaticAccessOnly' @paramRemoveItemProperty) + + # Remove "Print" from batch and .cmd files context menu + $null = (Remove-Item -Path 'Registry::HKEY_CLASSES_ROOT\batfile\shell\print\ProgrammaticAccessOnly' @paramRemoveItemProperty) + $null = (Remove-Item -Path 'Registry::HKEY_CLASSES_ROOT\cmdfile\shell\print\ProgrammaticAccessOnly' @paramRemoveItemProperty) + #endregion + + #region + # Remove "Rich Text Document" from context menu + $null = (Remove-Item -Path 'Registry::HKEY_CLASSES_ROOT\.rtf\ShellNew' @paramRemoveItemProperty) + + # Remove "Bitmap image" from context menu + $null = (Remove-Item -Path 'Registry::HKEY_CLASSES_ROOT\.bmp\ShellNew' @paramRemoveItemProperty) + #endregion + + #region + # Turn off Windows features + $features = @('FaxServicesClientPackage', 'LegacyComponents', 'MicrosoftWindowsPowerShellV2', 'MicrosoftWindowsPowershellV2Root', 'Printing-XPSServices-Features', 'Printing-PrintToPDFServices-Features', 'WorkFolders-Client', 'SMB1Protocol', 'SMB1Protocol-Client', 'SMB1Protocol-Server') + + $paramDisableWindowsOptionalFeature = @{ + Online = $true + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + + foreach ($feature in $features) + { + $paramGetWindowsOptionalFeature = @{ + Online = $true + FeatureName = $feature + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsOptionalFeature @paramGetWindowsOptionalFeature | Where-Object { + $_.State -ne 'Disabled' + } | Disable-WindowsOptionalFeature @paramDisableWindowsOptionalFeature) + } + + # Remove Windows capabilities + $IncludedApps = @('App.Support.QuickAssist*', 'Media.WindowsMediaPlayer*', 'Language.Handwriting*', 'Language.OCR*', 'Language.Speech*', 'Language.TextToSpeech*') + $OFS = '|' + $paramRemoveWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + + foreach ($IncludedApp in $IncludedApps) + { + try + { + $paramGetWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsCapability @paramGetWindowsCapability | Where-Object -FilterScript { + #$_.Name -cmatch $IncludedApps + ($_.Name -like $IncludedApp) -and ($_.State -eq 'Installed') + } | Remove-WindowsCapability @paramRemoveWindowsCapability) + } + catch + { + Write-Verbose -Message 'Most of the time: Permanent package cannot be uninstalled. And we know that!' + } + } + $OFS = ' ' + #endregion + #endregion + + #region + # Disable hibernation if the device is not a laptop + $paramGetCimInstance = @{ + ClassName = 'Win32_ComputerSystem' + ErrorAction = $SCT + WarningAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).PCSystemType -ne 2) + { + $null = (& "$env:windir\system32\powercfg.exe" /HIBERNATE OFF) + } + #endregion + + #region + $paramTestPath = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\WindowsMitigation' + WarningAction = $SCT + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\WindowsMitigation' + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + + $null = (New-Item @paramNewItem) + } + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\WindowsMitigation\UserPreference' + PropertyType = 'DWord' + Value = '3' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Enable "Network Discovery" and "File and Printers Sharing" for workgroup networks + $paramGetCimInstance = @{ + ClassName = 'CIM_ComputerSystem' + WarningAction = $SCT + ErrorAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).PartOfDomain -eq $false) + { + $FirewallRules = @( + # File and printer sharing + '@FirewallAPI.dll,-32752', + # Network discovery + '@FirewallAPI.dll,-28502' + ) + $paramSetNetFirewallRule = @{ + Group = $FirewallRules + Profile = 'Private' + Enabled = 'True' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-NetFirewallRule @paramSetNetFirewallRule) + } + #endregion + + #region + # Turn off Cortana autostarting + $paramGetAppxPackage = @{ + Name = 'Microsoft.549981C3F5F10' + WarningAction = $SCT + ErrorAction = $SCT + } + if (Get-AppxPackage @paramGetAppxPackage) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'Registry::HKEY_CLASSES_ROOT\Local Settings\Software\Microsoft\Windows\CurrentVersion\AppModel\SystemAppData\Microsoft.549981C3F5F10_8wekyb3d8bbwe\CortanaStartupId' + PropertyType = 'DWord' + Value = '3' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + #endregion + + #region + # Turn on hardware-accelerated GPU scheduling. Restart needed + # Determining whether the PC has a dedicated GPU to use this feature + $paramGetCimInstance = @{ + ClassName = 'CIM_VideoController' + WarningAction = $SCT + ErrorAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance | Where-Object -FilterScript { + $_.AdapterDACType -ne 'Internal' + })) + { + # Determining whether an OS is not installed on a virtual machine + $paramGetCimInstance = @{ + ClassName = 'CIM_ComputerSystem' + WarningAction = $SCT + ErrorAction = $SCT + } + if ((Get-CimInstance @paramGetCimInstance).Model -notmatch 'Virtual') + { + # Checking whether a WDDM verion is 2.7 or higher + $paramGetItemPropertyValue = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\FeatureSetUsage' + Name = 'WddmVersion_Min' + WarningAction = $SCT + ErrorAction = $SCT + } + + if ((Get-ItemPropertyValue @paramGetItemPropertyValue) -ge 2700) + { + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SYSTEM\CurrentControlSet\Control\GraphicsDrivers\HwSchMode' + PropertyType = 'DWord' + Value = '2' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + } + } + #endregion + + #region + # Turn on events auditing generated when a process is created or starts + $null = (& "$env:windir\system32\auditpol.exe" /set /subcategory:"{0CCE922B-69AE-11D9-BED3-505054503030}" /success:enable /failure:enable) + #endregion + + #region + # Log for all Windows PowerShell modules + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\EnableModuleLogging' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ModuleLogging\ModuleNames\*' + PropertyType = 'String' + Value = '*' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Log all PowerShell scripts input to the Windows PowerShell event log + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging\EnableScriptBlockLogging' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region + # Turn on Microsoft Defender Exploit Guard network protection + $paramSetMpPreference = @{ + EnableNetworkProtection = 'Enabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + + # Turn on detection for potentially unwanted applications and block them + $paramSetMpPreference = @{ + PUAProtection = 'Enabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + + # Run Microsoft Defender within a sandbox + $null = (& "$env:windir\system32\setx.exe" /M MP_FORCE_USE_SANDBOX 1) + #endregion + + #region + # Make this connection private + $paramResolveDnsName = @{ + Name = 'kms.enatec.net' + Type = 'A' + WarningAction = $SCT + ErrorAction = $SCT + } + if (Resolve-DnsName @paramResolveDnsName | Where-Object { + (($_.Type -eq 'A') -and ($_.IPAddress -ne '0.0.0.0')) + }) + { + # Cleanup + $InterfaceAliasInfo = $null + + <# + With Windows 10 20H2 some NICs report a limited connection! + + Let us try this as a workaround: + The first call try to find the NIC with an Internet connection, + if this fails the second call will try to get the NIC with a working + connection via Test-NetConnection instead of Get-NetConnectionProfile. + + Not perfect, but the "No Internet Access" state cause some issues! + #> + try + { + $paramGetNetConnectionProfile = @{ + IPv4Connectivity = 'Internet' + ErrorAction = 'Stop' + WarningAction = $SCT + } + $InterfaceAliasInfo = ((Get-NetConnectionProfile @paramGetNetConnectionProfile).InterfaceAlias) + } + catch + { + # Cleanup + $TestNetConnection = $null + + <# + This is a quick and dirty Workaround: + Figure out if we have a working Internet connection: + Try a connection via Test-NetConnection on Port 443/TCP (HTTPS) to + random Microsoft provided IP/Host. + + - Thanks Microsoft for the crappy NIC handling in Windows 10 20H2 - + #> + $paramTestNetConnection = @{ + Port = 443 + ErrorAction = $SCT + WarningAction = $SCT + } + $TestNetConnection = (Test-NetConnection @paramTestNetConnection) + + if ((($TestNetConnection).TcpTestSucceeded) -eq $true) + { + $InterfaceAliasInfo = (($TestNetConnection). InterfaceAlias) + } + } + + # Prevent NULL Pointer Exception - See workaround above! + if ($InterfaceAliasInfo) + { + $paramSetNetConnectionProfile = @{ + InterfaceAlias = $InterfaceAliasInfo + NetworkCategory = 'Private' + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Set-NetConnectionProfile @paramSetNetConnectionProfile) + } + else + { + Write-Verbose -Message 'Skipped: Could not get the required Network Connection Profile information' + } + } + #endregion + + #region MovedOver + #region DisableTailoredExperiences + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\Software\Policies\Microsoft\Windows\CloudContent\DisableTailoredExperiencesWithDiagnosticData' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableTailoredExperiences + + #region EnableActionCenter + $null = (Remove-ItemProperty -Path 'HKLM:\Software\Policies\Microsoft\Windows\Explorer' -Name 'DisableNotificationCenter' @paramRemoveItemProperty) + #endregion EnableActionCenter + + #region Office2016Telemetry + $paramConfirmRegistryItemProperty = @{ + Path = 'HKLM:\software\policies\microsoft\office\16.0\osm\enablelogging' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion Office2016Telemetry + #endregion MovedOver + + #region FinalTouches + # Create a task in the Task Scheduler to start Windows cleaning up - The task runs every 90 days + $keys = @('Delivery Optimization Files', 'Device Driver Packages', 'Previous Installations', 'Setup Log Files', 'Temporary Setup Files', 'Update Cleanup', 'Windows Defender', 'Windows Upgrade Log Files') + + foreach ($key in $keys) + { + $paramConfirmRegistryItemProperty = @{ + Path = ('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches\' + $key + 'StateFlags1337') + PropertyType = 'DWord' + Value = '2' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + + $paramNewScheduledTaskAction = @{ + Execute = 'cleanmgr.exe' + Argument = '/sagerun:1337' + WarningAction = $SCT + ErrorAction = $SCT + } + $action = (New-ScheduledTaskAction @paramNewScheduledTaskAction) + + $paramNewScheduledTaskTrigger = @{ + Daily = $true + DaysInterval = '90' + At = '9am' + WarningAction = $SCT + ErrorAction = $SCT + } + $trigger = (New-ScheduledTaskTrigger @paramNewScheduledTaskTrigger) + + $paramNewScheduledTaskSettingsSet = @{ + Compatibility = 'Win8' + StartWhenAvailable = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $settings = (New-ScheduledTaskSettingsSet @paramNewScheduledTaskSettingsSet) + + $paramNewScheduledTaskPrincipal = @{ + UserId = $env:USERNAME + RunLevel = 'Highest' + WarningAction = $SCT + ErrorAction = $SCT + } + $principal = (New-ScheduledTaskPrincipal @paramNewScheduledTaskPrincipal) + + $params = @{ + 'TaskName' = 'Update Cleanup' + 'Action' = $action + 'Trigger' = $trigger + 'Settings' = $settings + 'Principal' = $principal + 'Force' = $true + 'ErrorAction' = $SCT + } + $null = (Register-ScheduledTask @params) + + # Create a task in the Task Scheduler to clear the $env:SystemRoot\SoftwareDistribution\Download folder - The task runs on Thursdays every 4 weeks + $paramNewScheduledTaskAction = @{ + Execute = 'powershell.exe' + ErrorAction = $SCT + Argument = @" + `$getservice = Get-Service -Name wuauserv + `$getservice.WaitForStatus("Stopped", "01:00:00") + Get-ChildItem -Path `$env:SystemRoot\SoftwareDistribution\Download -Recurse -Force -ErrorAction SilentlyContinue | Remove-Item -Recurse -Force -ErrorAction SilentlyContinue +"@ + } + $action = (New-ScheduledTaskAction @paramNewScheduledTaskAction) + + $paramNewJobTrigger = @{ + Weekly = $true + WeeksInterval = '4' + DaysOfWeek = 'Thursday' + At = '9am' + ErrorAction = $SCT + } + $trigger = (New-JobTrigger @paramNewJobTrigger) + + $paramNewScheduledTaskSettingsSet = @{ + Compatibility = 'Win8' + StartWhenAvailable = $true + ErrorAction = $SCT + } + $settings = (New-ScheduledTaskSettingsSet @paramNewScheduledTaskSettingsSet) + + $paramNewScheduledTaskPrincipal = @{ + UserId = 'NT AUTHORITY\SYSTEM' + RunLevel = 'Highest' + ErrorAction = $SCT + } + $principal = (New-ScheduledTaskPrincipal @paramNewScheduledTaskPrincipal) + + $params = @{ + 'TaskName' = 'SoftwareDistribution' + 'Action' = $action + 'Trigger' = $trigger + 'Settings' = $settings + 'Principal' = $principal + 'Force' = $true + 'ErrorAction' = $SCT + } + $null = (Register-ScheduledTask @params) + + # Create a task in the Task Scheduler to clear the $env:TEMP folder - The task runs every 62 days + $paramNewScheduledTaskAction = @{ + Execute = 'powershell.exe' + ErrorAction = $SCT + Argument = @" + Get-ChildItem -Path `$env:TEMP -Force -Recurse -ErrorAction SilentlyContinue | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue +"@ + } + $action = (New-ScheduledTaskAction @paramNewScheduledTaskAction) + + $paramNewScheduledTaskTrigger = @{ + Daily = $true + DaysInterval = '62' + At = '9am' + ErrorAction = $SCT + } + $trigger = (New-ScheduledTaskTrigger @paramNewScheduledTaskTrigger) + + $paramNewScheduledTaskSettingsSet = @{ + Compatibility = 'Win8' + StartWhenAvailable = $true + ErrorAction = $SCT + } + $settings = (New-ScheduledTaskSettingsSet @paramNewScheduledTaskSettingsSet) + + $paramNewScheduledTaskPrincipal = @{ + UserId = 'NT AUTHORITY\SYSTEM' + RunLevel = 'Highest' + ErrorAction = $SCT + } + $principal = (New-ScheduledTaskPrincipal @paramNewScheduledTaskPrincipal) + + $params = @{ + 'TaskName' = 'Temp' + 'Action' = $action + 'Trigger' = $trigger + 'Settings' = $settings + 'Principal' = $principal + 'Force' = $true + 'ErrorAction' = $SCT + } + $null = (Register-ScheduledTask @params) + + # Turn off Windows features + $features = @('FaxServicesClientPackage', 'LegacyComponents', 'MicrosoftWindowsPowerShellV2', 'MicrosoftWindowsPowershellV2Root', 'Printing-XPSServices-Features', 'Printing-PrintToPDFServices-Features', 'WorkFolders-Client', 'SMB1Protocol', 'SMB1Protocol-Client', 'SMB1Protocol-Server') + + foreach ($feature in $features) + { + $paramGetWindowsOptionalFeature = @{ + Online = $true + FeatureName = $feature + WarningAction = $SCT + ErrorAction = $SCT + } + $paramDisableWindowsOptionalFeature = @{ + Online = $true + NoRestart = $true + WarningAction = $SCT + ErrorAction = $SCT + } + + $null = (Get-WindowsOptionalFeature @paramGetWindowsOptionalFeature | Where-Object { + $_.State -ne 'Disabled' + } | Disable-WindowsOptionalFeature @paramDisableWindowsOptionalFeature) + } + + # Remove Windows capabilities + $IncludedApps = @('App.Support.QuickAssist*', 'Media.WindowsMediaPlayer*', 'Browser.InternetExplorer*', 'Language.Handwriting*', 'Language.OCR*', 'Language.Speech*', 'Language.TextToSpeech*') + $OFS = '|' + foreach ($IncludedApp in $IncludedApps) + { + try + { + $paramGetWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $paramRemoveWindowsCapability = @{ + Online = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-WindowsCapability @paramGetWindowsCapability | Where-Object -FilterScript { + #$_.Name -cmatch $IncludedApps + ($_.Name -like $IncludedApp) -and ($_.State -eq 'Installed') + } | Remove-WindowsCapability @paramRemoveWindowsCapability) + } + catch + { + Write-Verbose -Message 'Most of the time: Permanent package cannot be uninstalled. And we know that!' + } + } + $OFS = ' ' + #endregion FinalTouches +} + +end +{ + $paramGetCommand = @{ + Name = 'Set-MpPreference' + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Enabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapUser.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapUser.ps1 new file mode 100644 index 0000000..c963309 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-BootstrapUser.ps1 @@ -0,0 +1,1755 @@ +#requires -Version 5.0 + +<# + .SYNOPSIS + Bootstrap Windows 10 User Profile + + .DESCRIPTION + Bootstrap Windows 10 User Profile with the default configuration. + Tested with the latest Windows 10 (Enterprise and Professional) releases. + + .NOTES + Lot of the stuff of this version is adopted from Disassembler + + Version 1.7.2 + + .LINK + http://enatec.io + + .LINK + https://github.com/Disassembler0/Win10-Initial-Setup-Script +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Bootstrap Windows 10 User Profile' + + #region GlobalDefaults + $SCT = 'SilentlyContinue' + + $paramGetCommand = @{ + Name = 'Set-MpPreference' + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Disabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + } + + $paramRemoveItemProperty = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + #endregion GlobalDefaults + + #region HelperFunction + function Confirm-RegistryItemProperty + { + <# + .SYNOPSIS + Enforce that an item property in the registry + + .DESCRIPTION + Enforce that an item property in the registry + + .PARAMETER Path + Registry Path + + .PARAMETER PropertyType + The Property Type + + .PARAMETER Value + The Registry Value to set + + .EXAMPLE + PS C:\> Confirm-RegistryItemProperty -Path 'HKLM:\System\CurrentControlSet\Services\PimIndexMaintenanceSvc\Start' -PropertyType 'DWord' -Value '1' + + .NOTES + Fixed version of the Helper: + Recreate the Key if the Type is wrong (Possible cause the old version had a glitsch) + #> + [CmdletBinding(ConfirmImpact = 'None', SupportsShouldProcess)] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [Alias('RegistryPath')] + [string] + $Path, + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + HelpMessage = 'Add help message for user')] + [ValidateNotNullOrEmpty()] + [Alias('Property', 'Type')] + [string] + $PropertyType, + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [AllowEmptyCollection()] + [AllowEmptyString()] + [AllowNull()] + [Alias('RegistryValue')] + $Value + ) + + begin + { + #region + $SCT = 'SilentlyContinue' + #endregion + } + + process + { + $paramTestPath = @{ + Path = ($Path | Split-Path) + WarningAction = $SCT + ErrorAction = $SCT + } + if (-Not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = ($Path | Split-Path) + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramGetItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + WarningAction = $SCT + ErrorAction = $SCT + } + if (-Not (Get-ItemProperty @paramGetItemProperty)) + { + $paramNewItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + PropertyType = $PropertyType + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + #region Workaround + $paramGetItem = @{ + Path = ($Path | Split-Path) + ErrorAction = $SCT + WarningAction = $SCT + } + if (((Get-Item @paramGetItem).GetValueKind(($Path | Split-Path -Leaf))) -ne $PropertyType) + { + # The PropertyType is wrong! This might be an issue of our old version! Sorry for the glitsch + $paramRemoveItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Remove-ItemProperty @paramRemoveItemProperty) + + $paramNewItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + PropertyType = $PropertyType + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + # Regular handling: PropertyType was correct + $paramSetItemProperty = @{ + Path = ($Path | Split-Path) + Name = ($Path | Split-Path -Leaf) + Value = $Value + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + #endregion Workaround + } + } + } + #endregion HelperFunction +} + +process +{ + #region PrivacyTweaks + #region DisableWindowsErrorDialog + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\Windows Error Reporting\DontShowUI' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWindowsErrorDialog + + #region DisableAdvertisingInfo + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAdvertisingInfo + + #region DisableWebSearch + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search\BingSearchEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search\CortanaConsent' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWebSearch + + #region + # Do not suggest ways I can finish setting up my device to get the most out of Windows (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\UserProfileEngagement\ScoobeSystemSettingEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region DisableAppSuggestions + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\ContentDeliveryAllowed' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\OemPreInstalledAppsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\PreInstalledAppsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\PreInstalledAppsEverEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SilentInstalledAppsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-310093Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-314559Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338387Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-353694Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338388Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338389Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338393Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-338388Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-353696Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SubscribedContent-353698Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager\SystemPaneSuggestionsEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Empty placeholder tile collection in registry cache and restart Start Menu process to reload the cache + if ([Environment]::OSVersion.Version.Build -ge 17134) + { + $paramGetItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\*windows.data.placeholdertilecollection\Current' + WarningAction = $SCT + ErrorAction = $SCT + } + $key = (Get-ItemProperty @paramGetItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = ($key.PSPath + 'Data') + PropertyType = 'Binary' + Value = $key.Data[0 .. 15] + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramStopProcess = @{ + Name = 'ShellExperienceHost' + Force = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Stop-Process @paramStopProcess) + } + #endregion DisableAppSuggestions + + #region DisableActivityHistory + #endregion DisableActivityHistory + + #region DisableBackgroundApps + $paramGetChildItem = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\BackgroundAccessApplications' + Exclude = 'Microsoft.Windows.Cortana*', 'Microsoft.Windows.ShellExperienceHost*' + WarningAction = $SCT + ErrorAction = $SCT + } + + $null = (Get-ChildItem @paramGetChildItem | ForEach-Object -Process { + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + 'Disabled') + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + 'DisabledByUser') + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + }) + #endregion DisableBackgroundApps + + #region + # Make the "Open", "Print", "Edit" context menu items available, when more than 15 selected + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\MultipleInvokePromptMinimum' + PropertyType = 'DWord' + Value = '300' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region DisableFeedback + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Siuf\Rules\NumberOfSIUFInPeriod' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableFeedback + + #region DisableTailoredExperiences + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Privacy\TailoredExperiencesWithDiagnosticDataEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableTailoredExperiences + + #region DisableAdvertisingID + #endregion DisableAdvertisingID + + #region DisableWebLangList + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\International\User Profile\HttpAcceptLanguageOptOut' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableWebLangList + + #region DisableCortana + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Personalization\Settings\AcceptedPrivacyPolicy' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\InputPersonalization\RestrictImplicitTextCollection' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\InputPersonalization\RestrictImplicitInkCollection' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\InputPersonalization\TrainedDataStore\HarvestContacts' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableCortana + #endregion PrivacyTweaks + + #region SecurityTweaks + #region + # Turn off Windows Script Host (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows Script Host\Settings\Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region AppAndBrowser_EdgeSmartScreenOff + # Dismiss Microsoft Defender offer in the Windows Security about to turn on the SmartScreen filter for Microsoft Edge + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows Security Health\State\AppAndBrowser_EdgeSmartScreenOff' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion AppAndBrowser_EdgeSmartScreenOff + + #region HideDefenderAccountProtectionWarning + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows Security Health\State\AccountProtection_MicrosoftAccount_Disconnected' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideDefenderAccountProtectionWarning + + #region DisableDownloadBlocking + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Attachments\SaveZoneInformation' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableDownloadBlocking + #endregion SecurityTweaks + + #region LegacyDefaultPrinterMode + # Do not let Windows manage default printer + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Windows\LegacyDefaultPrinterMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion LegacyDefaultPrinterMode + + #region ServiceTweaks + #region DisableSharedExperiences + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CDP\RomeSdkChannelUserAuthzPolicy' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableSharedExperiences + + #region DisableClipboardHistory + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Clipboard' -Name 'EnableClipboardHistory' @paramRemoveItemProperty) + #endregion DisableClipboardHistory + + #region DisableAutoplay + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoplayHandlers\DisableAutoplay' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAutoplay + + #region + # Automatically save my restartable apps when signing out and restart them after signing in (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\RestartApps' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region EnableStorageSense + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\01' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\StoragePoliciesNotified' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Run Storage Sense every month + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\2048' + PropertyType = 'DWord' + Value = '30' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Delete temporary files that apps aren't using + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\04' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Delete files in recycle bin if they have been there for over 30 days + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\08' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\256' + PropertyType = 'DWord' + Value = '30' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Never delete files in "Downloads" folder + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\512' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableStorageSense + + #region EnableRecycleBin + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' -Name 'NoRecycleFiles' @paramRemoveItemProperty) + #endregion EnableRecycleBin + #endregion ServiceTweaks + + #region UITweaks + #region EnablePerProcessSystemDPI + # Let Windows try to fix apps so they're not blurry + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\EnablePerProcessSystemDPI' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnablePerProcessSystemDPI + + #region EnableActionCenter + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Policies\Microsoft\Windows\Explorer' -Name 'DisableNotificationCenter' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\PushNotifications' -Name 'ToastEnabled'@paramRemoveItemProperty) + #endregion EnableActionCenter + + #region EnableAeroShake + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'DisallowShaking' @paramRemoveItemProperty) + #endregion EnableAeroShake + + #region DisableAccessibilityKeys + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\StickyKeys\Flags' + PropertyType = 'String' + Value = '506' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\ToggleKeys\Flags' + PropertyType = 'String' + Value = '58' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\Keyboard Response\Flags' + PropertyType = 'String' + Value = '122' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableAccessibilityKeys + + #region ShowTaskManagerDetails + $paramStartProcess = @{ + WindowStyle = 'Hidden' + FilePath = 'taskmgr.exe' + PassThru = $true + WarningAction = $SCT + ErrorAction = $SCT + } + + $taskmgr = (Start-Process @paramStartProcess) + $timeout = 30000 + $sleep = 100 + $preferences = $null + do + { + $null = (Start-Sleep -Milliseconds $sleep) + $timeout -= $sleep + $paramGetItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\TaskManager' + Name = 'Preferences' + WarningAction = $SCT + ErrorAction = $SCT + } + + $preferences = (Get-ItemProperty @paramGetItemProperty) + } + until ($preferences -or $timeout -le 0) + $null = ($taskmgr | Stop-Process -WarningAction $SCT -ErrorAction $SCT) + + if ($preferences) + { + $preferences.Preferences[28] = 0 + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\TaskManager\Preferences' + PropertyType = 'Binary' + Value = $preferences.Preferences + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + #endregion ShowTaskManagerDetails + + #region ShowFileOperationsDetails + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\OperationStatusManager\EnthusiastMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowFileOperationsDetails + + #region EnableFileDeleteConfirm + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer\ConfirmFileDelete' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableFileDeleteConfirm + + #region HideTaskbarSearch + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search\SearchboxTaskbarMode' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideTaskbarSearch + + #region HideTaskView + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowTaskViewButton' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideTaskView + + #region ShowSmallTaskbarIcons + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\TaskbarSmallIcons' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowSmallTaskbarIcons + + #region SetTaskbarCombineAlways + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'TaskbarGlomLevel' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'MMTaskbarGlomLevel' @paramRemoveItemProperty) + #endregion SetTaskbarCombineAlways + + #region HideTaskbarPeopleIcon + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\People\PeopleBand' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideTaskbarPeopleIcon + + #region HideTrayIcons + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer' -Name 'NoAutoTrayNotify' @paramRemoveItemProperty) + #endregion HideTrayIcons + + #region HideSecondsFromTaskbar + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'ShowSecondsInSystemClock' @paramRemoveItemProperty) + #endregion HideSecondsFromTaskbar + + #region SetControlPanelSmallIcons + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\StartupPage' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\AllItemsIconView' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetControlPanelSmallIcons + + #region DisableShortcutInName + $paramNewItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\' + Name = 'link' + PropertyType = 'Binary' + Value = ([byte[]](00, 00, 00, 00)) + Force = $true + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + #endregion DisableShortcutInName + + #region PrintScreenKeyForSnippingEnabled + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Keyboard\PrintScreenKeyForSnippingEnabled' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion PrintScreenKeyForSnippingEnabled + + #region SetVisualFXPerformance + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\DragFullWindows' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\MenuShowDelay' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\UserPreferencesMask' + PropertyType = 'Binary' + Value = ([byte[]](144, 18, 3, 128, 16, 0, 0, 0)) + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\WindowMetrics\MinAnimate' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Keyboard\KeyboardDelay' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewAlphaSelect' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ListviewShadow' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\TaskbarAnimations' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects\VisualFXSetting' + PropertyType = 'DWord' + Value = 3 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\DWM\EnableAeroPeek' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetVisualFXPerformance + + #region EnableTitleBarColor + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\DWM\ColorPrevalence' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableTitleBarColor + + #region DisableDynamicScrollbars + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Accessibility\DynamicScrollbars' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableDynamicScrollbars + + #region RemoveENKeyboard + $langs = (Get-WinUserLanguageList -ErrorAction $SCT) + $null = (Set-WinUserLanguageList -LanguageList ($langs | Where-Object { + $_.LanguageTag -ne 'en-US' + }) -Force -ErrorAction $SCT) + #endregion RemoveENKeyboard + + #region EnableEnhPointerPrecision + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Mouse\MouseSpeed' + PropertyType = 'String' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Mouse\MouseThreshold1' + PropertyType = 'String' + Value = '6' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Mouse\MouseThreshold2' + PropertyType = 'String' + Value = '10' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableEnhPointerPrecision + + #region DisableLiveTilesPermanently + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\PushNotifications\NoTileApplicationNotification' + PropertyType = 'String' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableLiveTilesPermanently + + #region ToastNotificationsToTop + # Move Toast Notifications to Top of Screen + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\DisplayToastAtBottom' + PropertyType = 'String' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ToastNotificationsToTop + + #region SetSoundSchemeNone + $SoundScheme = '.None' + $paramGetChildItem = @{ + Path = 'HKCU:\AppEvents\Schemes\Apps\*\*' + ErrorAction = $SCT + } + $null = (Get-ChildItem @paramGetChildItem | ForEach-Object { + # If scheme keys do not exist in an event, create empty ones (similar behavior to Sound control panel). + $paramTestPath = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramTestPath = @{ + Path = ($_.PsPath + '\.Current') + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = ($_.PsPath + '\.Current') + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + # Get a regular string from any possible kind of value, i.e. resolve REG_EXPAND_SZ, copy REG_SZ or empty from non-existing. + $paramGetItemProperty = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + Name = '(Default)' + ErrorAction = $SCT + } + $Data = ((Get-ItemProperty @paramGetItemProperty).'(Default)') + + if ($Data) + { + # Replace any kind of value with a regular string (similar behavior to Sound control panel). + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + '\' + $SoundScheme) + Name = '(Default)' + PropertyType = 'String' + Value = $Data + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + # Copy data from source scheme to current. + $paramConfirmRegistryItemProperty = @{ + Path = ($_.PsPath + '\.Current') + Name = '(Default)' + PropertyType = 'String' + Value = $Data + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + } + }) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\AppEvents\Schemes\(Default)' + PropertyType = 'String' + Value = $SoundScheme + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetSoundSchemeNone + + #region DisableF1HelpKey + $paramTestPath = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32' + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32' + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win32\(Default)' + PropertyType = 'String' + Value = '' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramTestPath = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64' + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64' + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Classes\TypeLib\{8cec5860-07a1-11d9-b15e-000d56bfe6ee}\1.0\0\win64\(Default)' + PropertyType = 'String' + Value = '' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableF1HelpKey + #endregion UITweaks + + #region ExplorerUITweaks + #region DisableXboxGamebar + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\GameDVR\AppCaptureEnabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_Enabled' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\GameBar\ShowStartupPanel' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableXboxGamebar + + #region HideExplorerTitleFullPath + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\CabinetState' -Name 'FullPath' @paramRemoveItemProperty) + #endregion HideExplorerTitleFullPath + + #region ShowKnownExtensions + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideFileExt' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowKnownExtensions + + #region ShowHiddenFiles + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Hidden' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowHiddenFiles + + #region HideSuperHiddenFiles + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowSuperHidden' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideSuperHiddenFiles + + #region ShowEmptyDrives + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideDrivesWithNoMedia' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowEmptyDrives + + #region ShowFolderMergeConflicts + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideMergeConflicts' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowFolderMergeConflicts + + #region EnableNavPaneExpand + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\NavPaneExpandToCurrentFolder' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableNavPaneExpand + + #region MMTaskbarMode + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\MMTaskbarMode' + PropertyType = 'DWord' + Value = '2' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion MMTaskbarMode + + #region HideNavPaneAllFolders + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'NavPaneShowAllFolders' @paramRemoveItemProperty) + #endregion HideNavPaneAllFolders + + #region EnableFolderSeparateProcess + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\SeparateProcess' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableFolderSeparateProcess + + #region DisableRestoreFldrWindows + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced' -Name 'PersistBrowsers' @paramRemoveItemProperty) + #endregion DisableRestoreFldrWindows + + #region ShowEncCompFilesColor + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowEncryptCompressedColor' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowEncCompFilesColor + + #region DisableSharingWizard + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\SharingWizardOn' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableSharingWizard + + #region ShowSelectCheckboxes + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\AutoCheckSelect' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowSelectCheckboxes + + #region ShowSyncNotifications + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowSyncProviderNotifications' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowSyncNotifications + + #region HideRecentShortcuts + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ShowRecent' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\ShowFrequent' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideRecentShortcuts + + #region SetExplorerThisPC + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\LaunchTo' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion SetExplorerThisPC + + #region HideQuickAccess + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\HubMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideQuickAccess + + #region ShowRecycleBinOnDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{645FF040-5081-101B-9F08-00AA002F954E}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{645FF040-5081-101B-9F08-00AA002F954E}' @paramRemoveItemProperty) + #endregion ShowRecycleBinOnDesktop + + #region ShowThisPCOnDesktop + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu\{20D04FE0-3AEA-1069-A2D8-08002B30309D}' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel\{20D04FE0-3AEA-1069-A2D8-08002B30309D}' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ShowThisPCOnDesktop + + #region HideUserFolderFromDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{59031a47-3f72-44a7-89c5-5595fe6b30ee}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{59031a47-3f72-44a7-89c5-5595fe6b30ee}' @paramRemoveItemProperty) + #endregion HideUserFolderFromDesktop + + #region HideControlPanelFromDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{5399E694-6CE5-4D6C-8FCE-1D8870FDCBA0}' @paramRemoveItemProperty) + #endregion HideControlPanelFromDesktop + + #region HideNetworkFromDesktop + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\ClassicStartMenu' -Name '{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}' @paramRemoveItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\HideDesktopIcons\NewStartPanel' -Name '{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}' @paramRemoveItemProperty) + #endregion HideNetworkFromDesktop + + #region HideBuildNumberFromDesktop + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\PaintDesktopVersion' + PropertyType = 'DWord' + Value = '0' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion HideBuildNumberFromDesktop + + #region ScreenSaver + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\ScreenSaveActive' + PropertyType = 'String' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\ScreenSaverIsSecure' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\ScreenSaveTimeOut' + PropertyType = 'DWord' + Value = '600' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\scrnsave.exe' + PropertyType = 'String' + Value = ($env:windir + '\system32\scrnsave.scr') + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion ScreenSaver + + #region + # Do not add the "- Shortcut" suffix to the file name of created shortcuts (current user only) + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\NamingTemplates\ShortcutNameTemplate' + PropertyType = 'String' + Value = '%s.lnk' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion + + #region DisableThumbnails + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\IconsOnly' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableThumbnails + + #region DisableThumbnailCache + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\DisableThumbnailCache' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableThumbnailCache + + #region DisableThumbsDBOnNetwork + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\DisableThumbsDBOnNetworkFolders' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableThumbsDBOnNetwork + + #region DisableDesktopWallpaperQualityReduction + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Control Panel\Desktop\JPEGImportQuality' + PropertyType = 'DWord' + Value = '100' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableDesktopWallpaperQualityReduction + + #region RemoveMicrosoftEdgeShortcut + $paramGetItemPropertyValue = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders' + Name = 'Desktop' + ErrorAction = $SCT + } + $Value = (Get-ItemPropertyValue @paramGetItemPropertyValue) + $null = (Remove-Item -Path ($Value + '\Microsoft Edge.lnk') @paramRemoveItemProperty) + #endregion RemoveMicrosoftEdgeShortcut + + #region RemoveHPSupportAssistantShortcut + $null = (Remove-Item -Path "$env:PUBLIC\Desktop\HP Support Assistant.lnk" @paramRemoveItemProperty) + #endregion RemoveHPSupportAssistantShortcut + #endregion ExplorerUITweaks + + #region ApplicationTweaks + #region DisableFullscreenOptims + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_DXGIHonorFSEWindowsCompatible' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_FSEBehavior' + PropertyType = 'DWord' + Value = 2 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_FSEBehaviorMode' + PropertyType = 'DWord' + Value = 2 + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\System\GameConfigStore\GameDVR_HonorUserFSEBehaviorMode' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion DisableFullscreenOptims + + if (-not ($env:COMPUTERNAME -match 'ENSHARED-')) + { + #region OneDriveInsider + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\OneDrive\EnableTeamTier_Internal' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\OneDrive\EnableFasterRingUpdate' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion OneDriveInsider + + #region EnableADALOneDrive + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\OneDrive\EnableADAL' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion EnableADALOneDrive + + #region OneDriveEnableHoldTheFile + # Users can choose how to handle Office files in conflict + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\OneDrive\EnableHoldTheFile' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregionEnableHoldTheFile + + #region OneDriveEnableAllOcsiClients + # Coauthoring and in-app sharing for Office files + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\SOFTWARE\Microsoft\OneDrive\EnableAllOcsiClients' + PropertyType = 'DWord' + Value = '1' + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + #endregion OneDriveEnableAllOcsiClients + } + #endregion ApplicationTweaks + + #region Unpinning + #region UnpinStartMenuTiles + # TODO: Convert to Switch + <# + if ([Environment]::OSVersion.Version.Build -ge 15063 -And [Environment]::OSVersion.Version.Build -le 16299) + { + Get-ChildItem -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount' -Include '*.group' -Recurse -WarningAction $SCT -ErrorAction $SCT | ForEach-Object { + $Data = ((Get-ItemProperty -Path ($_.PsPath + '\Current') -Name 'Data' -WarningAction $SCT -ErrorAction $SCT).Data -Join ',') + $Data = ($Data.Substring(0, $Data.IndexOf(',0,202,30') + 9) + ',0,202,80,0,0') + + $null = (Confirm-RegistryItemProperty -Path ($_.PsPath + '\Current\Data') -PropertyType Binary -Value $Data.Split(',') -WarningAction $SCT -ErrorAction $SCT) + } + } + elseif ([Environment]::OSVersion.Version.Build -ge 17134) + { + $key = (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\CloudStore\Store\Cache\DefaultAccount\*start.tilegrid`$windows.data.curatedtilecollection.tilecollection\Current" -WarningAction $SCT -ErrorAction $SCT) + $Data = $key.Data[0 .. 25] + ([byte[]](202, 50, 0, 226, 44, 1, 1, 0, 0)) + + $null = (Confirm-RegistryItemProperty -Path ($key.PSPath + '\Data') -PropertyType Binary -Value $Data -ErrorAction $SCT) + + $null = (Stop-Process -Name 'ShellExperienceHost' -Force -WarningAction $SCT -ErrorAction $SCT) + } + #> + #endregion UnpinStartMenuTiles + + #region UnpinTaskbarIcons + $paramConfirmRegistryItemProperty = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband\Favorites' + PropertyType = 'Binary' + Value = ([byte[]](255)) + ErrorAction = $SCT + } + $null = (Confirm-RegistryItemProperty @paramConfirmRegistryItemProperty) + $null = (Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband' -Name 'FavoritesResolve' @paramRemoveItemProperty) + #endregion UnpinTaskbarIcons + #endregion Unpinning + + #region FinalTouches + #region PowerShellProfiles + # Create all PowerShell related Profiles as dummy (empty) + $AllSystemProfiles = @( + (($PROFILE).CurrentUserCurrentHost) + (($PROFILE).CurrentUserAllHosts) + (($PROFILE).AllUsersCurrentHost) + (($PROFILE).AllUsersAllHosts) + ($PSHOME + '\Microsoft.VSCode_profile.ps1') + ) + + foreach ($SystemProfile in $AllSystemProfiles) + { + $paramTestPath = @{ + Path = $SystemProfile + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + ItemType = 'File' + Path = $SystemProfile + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + } + #endregion PowerShellProfiles + + # Restart Start menu + $paramStopProcess = @{ + Name = 'StartMenuExperienceHost' + Force = $true + ErrorAction = $SCT + } + $null = (Stop-Process @paramStopProcess) + + # Refresh desktop icons, environment variables and taskbar without restarting File Explorer + $UpdateEnvExplorerAPI = @{ + Namespace = 'WinAPI' + Name = 'UpdateEnvExplorer' + Language = 'CSharp' + MemberDefinition = @' +private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff); +private const int WM_SETTINGCHANGE = 0x1a; +private const int SMTO_ABORTIFHUNG = 0x0002; +[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] +static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam); +[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)] +private static extern IntPtr SendMessageTimeout(IntPtr hWnd, int Msg, IntPtr wParam, string lParam, int fuFlags, int uTimeout, IntPtr lpdwResult); +[DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = false)] +private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); +public static void Refresh() +{ + // Update desktop icons + SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero); + // Update environment variables + SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero); + // Update taskbar + SendNotifyMessage(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, "TraySettings"); +} +'@ + } + + if (-not ('WinAPI.UpdateEnvExplorer' -as [type])) + { + $null = (Add-Type @UpdateEnvExplorerAPI) + } + + $null = ([WinAPI.UpdateEnvExplorer]::Refresh()) + #endregion FinalTouches +} + +end +{ + $paramGetCommand = @{ + Name = 'Set-MpPreference' + ErrorAction = $SCT + } + if (Get-Command @paramGetCommand) + { + $paramSetMpPreference = @{ + EnableControlledFolderAccess = 'Enabled' + Force = $true + ErrorAction = $SCT + } + $null = (Set-MpPreference @paramSetMpPreference) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-MSIntuneDriverUpdate.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-MSIntuneDriverUpdate.ps1 new file mode 100644 index 0000000..e6b3e8a --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-MSIntuneDriverUpdate.ps1 @@ -0,0 +1,1214 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + + The purpose of this script is to automate the driver update process when enrolling devices through + Microsoft Intune. + + .DESCRIPTION + + This script will determine the model of the computer, manufacturer and operating system used then download, + extract & install the latest driver package from the manufacturer. At present Dell, HP and Lenovo devices + are supported. + + .NOTES + + FileName: Invoke-MSIntuneDriverUpdate.ps1 + + Author: Maurice Daly + Contact: @MoDaly_IT + Created: 2017-12-03 + Updated: 2017-12-05 + + Version history: + + 1.0.0 - (2017-12-03) Script created + 1.0.1 - (2017-12-05) Updated Lenovo matching SKU value and added regex matching for Computer Model values. + 1.0.2 - (2017-12-05) Updated to cater for language differences in OS architecture returned +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + # Set Temp & Log Location + $paramJoinPath = @{ + Path = 'c:\install' + ChildPath = '\SCConfigMgr' + ErrorAction = 'Stop' + } + [string]$TempDirectory = (Join-Path @paramJoinPath) + $paramJoinPath = @{ + Path = 'c:\temp' + ChildPath = '\SCConfigMgr' + ErrorAction = 'Stop' + } + [string]$LogDirectory = (Join-Path @paramJoinPath) + + # Create Temp Folder + $paramTestPath = @{ + Path = $TempDirectory + ErrorAction = $SCT + } + if ((Test-Path @paramTestPath ) -eq $false) + { + $paramNewItem = @{ + Path = $TempDirectory + ItemType = 'Dir' + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + # Create Logs Folder + $paramTestPath = @{ + Path = $LogDirectory + ErrorAction = $SCT + } + if ((Test-Path @paramTestPath ) -eq $false) + { + $paramNewItem = @{ + Path = $LogDirectory + ItemType = 'Dir' + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramPushLocation = @{ + Path = 'c:\install' + } + $null = (Push-Location @paramPushLocation) + + # Logging Function + function Write-CMLogEntry + { + <# + .SYNOPSIS + Describe purpose of "Write-CMLogEntry" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER Value + Describe parameter -Value. + + .PARAMETER Severity + Describe parameter -Severity. + + .PARAMETER FileName + Describe parameter -FileName. + + .EXAMPLE + Write-CMLogEntry -Value Value -Severity Value -FileName Value + Describe what this call does + + .NOTES + Place additional notes here. + + .LINK + URLs to related sites + The first link is opened by Get-Help -Online Write-CMLogEntry + + .INPUTS + List of input types that are accepted by this function. + + .OUTPUTS + List of output types produced by this function. + #> + [CmdletBinding(ConfirmImpact = 'None')] + param ( + [parameter(Mandatory, HelpMessage = 'Value added to the log file.')] + [ValidateNotNullOrEmpty()] + [string] + $Value, + [parameter(Mandatory, HelpMessage = 'Severity for the log entry. 1 for Informational, 2 for Warning and 3 for Error.')] + [ValidateNotNullOrEmpty()] + [ValidateSet('1', '2', '3')] + [string] + $Severity, + [ValidateNotNullOrEmpty()] + [string] + $FileName = 'Invoke-MSIntuneDriverUpdate.log' + ) + + begin + { + # Determine log file location + $paramJoinPath = @{ + Path = $LogDirectory + ChildPath = $FileName + ErrorAction = 'Stop' + } + $LogFilePath = (Join-Path @paramJoinPath) + + # Construct time stamp for log entry + $Time = -join @((Get-Date -Format 'HH:mm:ss.fff'), '+', (Get-WmiObject -Class Win32_TimeZone | Select-Object -ExpandProperty Bias)) + + # Construct date for log entry + $Date = (Get-Date -Format 'MM-dd-yyyy') + + # Construct context for log entry + $Context = $([Security.Principal.WindowsIdentity]::GetCurrent().Name) + + # Construct final log entry + $LogText = "" + } + + process + { + # Add value to log file + try + { + $paramAddContent = @{ + Value = $LogText + LiteralPath = $LogFilePath + Force = $true + ErrorAction = 'Stop' + } + $null = (Add-Content @paramAddContent) + } + catch + { + Write-Warning -Message "Unable to append log entry to Invoke-DriverUpdate.log file. Error message: $($_.Exception.Message)" + } + } + } + + # Define Dell Download Sources + $DellDownloadList = 'http://downloads.dell.com/published/Pages/index.html' + $DellDownloadBase = 'http://downloads.dell.com' + $DellDriverListURL = 'http://en.community.dell.com/techcenter/enterprise-client/w/wiki/2065.dell-command-deploy-driver-packs-for-enterprise-client-os-deployment' + $DellBaseURL = 'http://en.community.dell.com' + + # Define Dell Download Sources + $DellXMLCabinetSource = 'http://downloads.dell.com/catalog/DriverPackCatalog.cab' + $DellCatalogSource = 'http://downloads.dell.com/catalog/CatalogPC.cab' + + # Define Dell Cabinet/XL Names and Paths + $DellCabFile = [string]($DellXMLCabinetSource | Split-Path -Leaf -ErrorAction $SCT) + $DellCatalogFile = [string]($DellCatalogSource | Split-Path -Leaf -ErrorAction $SCT) + $DellXMLFile = $DellCabFile.Trim('.cab') + $DellXMLFile = $DellXMLFile + '.xml' + $DellCatalogXMLFile = $DellCatalogFile.Trim('.cab') + '.xml' + + # Define Dell Global Variables + $DellCatalogXML = $null + $DellModelXML = $null + $DellModelCabFiles = $null + + # Define HP Download Sources + $HPXMLCabinetSource = 'http://ftp.hp.com/pub/caps-softpaq/cmit/HPClientDriverPackCatalog.cab' + $HPSoftPaqSource = 'http://ftp.hp.com/pub/softpaq/' + $HPPlatFormList = 'http://ftp.hp.com/pub/caps-softpaq/cmit/imagepal/ref/platformList.cab' + + # Define HP Cabinet/XL Names and Paths + $HPCabFile = [string]($HPXMLCabinetSource | Split-Path -Leaf -ErrorAction $SCT) + $HPXMLFile = $HPCabFile.Trim('.cab') + $HPXMLFile = $HPXMLFile + '.xml' + $HPPlatformCabFile = [string]($HPPlatFormList | Split-Path -Leaf -ErrorAction $SCT) + $HPPlatformXMLFile = $HPPlatformCabFile.Trim('.cab') + $HPPlatformXMLFile = $HPPlatformXMLFile + '.xml' + + # Define HP Global Variables + $HPModelSoftPaqs = $null + $HPModelXML = $null + $HPPlatformXML = $null + + # Define Lenovo Download Sources + $script:LenovoXMLSource = 'https://download.lenovo.com/cdrt/td/catalog.xml' + + # Define Lenovo Cabinet/XL Names and Paths + $script:LenovoXMLFile = [string]($LenovoXMLSource | Split-Path -Leaf -ErrorAction $SCT) + + # Define Lenovo Global Variables + $LenovoModelDrivers = $null + $LenovoModelXML = $null + $LenovoModelType = $null + $LenovoSystemSKU = $null + + # Determine manufacturer + $ComputerManufacturer = ((Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Manufacturer).Trim()) + + Write-CMLogEntry -Value "Manufacturer determined as: $($ComputerManufacturer)" -Severity 1 + + # Determine manufacturer name and hardware information + switch -Wildcard ($ComputerManufacturer) + { + '*HP*' + { + $ComputerManufacturer = 'Hewlett-Packard' + $ComputerModel = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Model) + $SystemSKU = ((Get-CimInstance -ClassName MS_SystemInformation -NameSpace root\WMI).BaseBoardProduct) + } + '*Hewlett-Packard*' + { + $ComputerManufacturer = 'Hewlett-Packard' + $ComputerModel = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Model) + $SystemSKU = ((Get-CimInstance -ClassName MS_SystemInformation -NameSpace root\WMI).BaseBoardProduct) + } + '*Dell*' + { + $ComputerManufacturer = 'Dell' + $ComputerModel = (Get-WmiObject -Class Win32_ComputerSystem | Select-Object -ExpandProperty Model) + $SystemSKU = ((Get-CimInstance -ClassName MS_SystemInformation -NameSpace root\WMI).SystemSku) + } + '*Lenovo*' + { + $ComputerManufacturer = 'Lenovo' + $ComputerModel = (Get-WmiObject -Class Win32_ComputerSystemProduct | Select-Object -ExpandProperty Version) + $SystemSKU = (((Get-CimInstance -ClassName MS_SystemInformation -NameSpace root\WMI | Select-Object -ExpandProperty BIOSVersion).SubString(0, 4)).Trim()) + } + } + + Write-CMLogEntry -Value "Computer model determined as: $($ComputerModel)" -Severity 1 + + if (-not [string]::IsNullOrEmpty($SystemSKU)) + { + Write-CMLogEntry -Value "Computer SKU determined as: $($SystemSKU)" -Severity 1 + } + + # Get operating system name from version + switch -wildcard (Get-WmiObject -Class Win32_OperatingSystem | Select-Object -ExpandProperty Version) + { + '10.0*' + { + $OSName = 'Windows 10' + } + '6.3*' + { + $OSName = 'Windows 8.1' + } + '6.1*' + { + $OSName = 'Windows 7' + } + } + + Write-CMLogEntry -Value "Operating system determined as: $OSName" -Severity 1 + + # Get operating system architecture + switch -wildcard ((Get-CimInstance -ClassName Win32_operatingsystem).OSArchitecture) + { + '64-*' + { + $OSArchitecture = '64-Bit' + } + '32-*' + { + $OSArchitecture = '32-Bit' + } + } + + Write-CMLogEntry -Value "Architecture determined as: $OSArchitecture" -Severity 1 + + $WindowsVersion = ($OSName).Split(' ')[1] + + function DownloadDriverList + { + <# + .SYNOPSIS + Describe purpose of "DownloadDriverList" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .EXAMPLE + DownloadDriverList + Describe what this call does + + .NOTES + Place additional notes here. + #> + [CmdletBinding(ConfirmImpact = 'None')] + param () + + Write-CMLogEntry -Value '======== Download Model Link Information ========' -Severity 1 + + switch ($ComputerManufacturer) + { + 'Hewlett-Packard' + { + if ((Test-Path -Path $TempDirectory\$HPCabFile) -eq $false) + { + Write-CMLogEntry -Value '======== Downloading HP Product List ========' -Severity 1 + Write-CMLogEntry -Value "Info: Downloading HP driver pack cabinet file from $HPXMLCabinetSource" -Severity 1 + + try + { + $paramStartBitsTransfer = @{ + Source = $HPXMLCabinetSource + Destination = $TempDirectory + TransferPolicy = 'Always' + Priority = 'Foreground' + ErrorAction = 'Stop' + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + + Write-CMLogEntry -Value "Info: Expanding HP driver pack cabinet file: $HPXMLFile" -Severity 1 + + $null = (& "$env:windir\system32\expand.exe" "$TempDirectory\$HPCabFile" -F:* "$TempDirectory\$HPXMLFile") + } + catch + { + Write-CMLogEntry -Value "Error: $($_.Exception.Message)" -Severity 3 + } + } + # Read XML File + if (-not ($HPModelSoftPaqs)) + { + Write-CMLogEntry -Value "Info: Reading driver pack XML file - $TempDirectory\$HPXMLFile" -Severity 1 + + $paramGetContent = @{ + Path = ($TempDirectory + '\' + $HPXMLFile) + ErrorAction = $SCT + } + [xml]$script:HPModelXML = (Get-Content @paramGetContent) + + # Set XML Object + $null = ($HPModelXML.GetType().FullName) + $script:HPModelSoftPaqs = $HPModelXML.NewDataSet.HPClientDriverPackCatalog.ProductOSDriverPackList.ProductOSDriverPack + } + } + 'Dell' + { + if (-not (Test-Path -Path $TempDirectory\$DellCabFile)) + { + Write-CMLogEntry -Value 'Info: Downloading Dell product list' -Severity 1 + Write-CMLogEntry -Value "Info: Downloading Dell driver pack cabinet file from $DellXMLCabinetSource" -Severity 1 + + # Download Dell Model Cabinet File + try + { + $paramStartBitsTransfer = @{ + Source = $DellXMLCabinetSource + Destination = $TempDirectory + TransferPolicy = 'Always' + Priority = 'High' + ErrorAction = 'Stop' + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + + # Expand Cabinet File + Write-CMLogEntry -Value "Info: Expanding Dell driver pack cabinet file: $DellXMLFile" -Severity 1 + + $null = (& "$env:windir\system32\expand.exe" "$TempDirectory\$DellCabFile" -F:* "$TempDirectory\$DellXMLFile") + } + catch + { + Write-CMLogEntry -Value "Error: $($_.Exception.Message)" -Severity 3 + } + } + + if (-not ($DellModelXML)) + { + # Read XML File + Write-CMLogEntry -Value "Info: Reading driver pack XML file - $TempDirectory\$DellXMLFile" -Severity 1 + + $paramGetContent = @{ + Path = $TempDirectory + ReadCount = '\' + TotalCount = $DellXMLFile + ErrorAction = $SCT + } + [xml]$DellModelXML = (Get-Content @paramGetContent) + + # Set XML Object + $null = ($DellModelXML.GetType().FullName) + } + + $DellModelCabFiles = $DellModelXML.driverpackmanifest.driverpackage + } + 'Lenovo' + { + if (-not ($LenovoModelDrivers)) + { + try + { + $paramInvokeWebRequest = @{ + Uri = $LenovoXMLSource + ErrorAction = 'Stop' + } + [xml]$script:LenovoModelXML = (Invoke-WebRequest @paramInvokeWebRequest) + } + catch + { + Write-CMLogEntry -Value "Error: $($_.Exception.Message)" -Severity 3 + } + + # Read Web Site + Write-CMLogEntry -Value "Info: Reading driver pack URL - $LenovoXMLSource" -Severity 1 + + # Set XML Object + $null = ($LenovoModelXML.GetType().FullName) + $script:LenovoModelDrivers = $LenovoModelXML.Products + } + } + Default + { + Write-CMLogEntry -Value 'Unknown or unsupported Computer Manufacturer or OEM' -Severity 2 + } + } + } + + function FindLenovoDriver + { + <# + .SYNOPSIS + extract the link for the specified driver pack or application + + .DESCRIPTION + extract the link for the specified driver pack or application + + .PARAMETER URI + The string version of the URL + + .PARAMETER OS + Describe parameter -OS. + + .PARAMETER Architecture + A string containing 7, 8, or 10 depending on the os we are deploying i.e. 7, Win7, Windows 7 etc are all valid os strings + + .EXAMPLE + FindLenovoDriver -URI Value -OS Value -Architecture Value + extract the link for the specified driver pack or application + + .NOTES + #> + [CmdletBinding(ConfirmImpact = 'None')] + param ( + [parameter(Mandatory, HelpMessage = 'Provide the URL to parse.')] + [ValidateNotNullOrEmpty()] + [string] + $URI, + [parameter(Mandatory, HelpMessage = 'Specify the operating system.')] + [ValidateNotNullOrEmpty()] + [string] + $OS, + [string] + $Architecture + ) + + begin + { + # Case for direct link to a zip file + if ($URI.EndsWith('.zip')) + { + return $URI + } + + $err = @() + } + + process + { + # Get the content of the website + try + { + $paramInvokeWebRequest = @{ + Uri = $URI + ErrorAction = 'Stop' + } + $html = (Invoke-WebRequest @paramInvokeWebRequest) + } + catch + { + Write-CMLogEntry -Value "Error: $($_.Exception.Message)" -Severity 3 + } + + # Create an array to hold all the links to exe files + $Links = @() + $Links.Clear() + + # Determine if the URL resolves to the old download location + if ($URI -like '*olddownloads*') + { + #Quickly grab the links that end with exe + $Links = (($html.Links | Where-Object { + $_.href -like '*exe' + }) | Where-Object class -EQ -Value 'downloadBtn').href + } + + $Links = ((Select-String -Pattern '(http[s]?)(:\/\/)([^\s,]+.exe)(?=")' -InputObject (($html).Rawcontent) -AllMatches ErrorAction $SCT).Matches.Value) + + if ($Links.Count -eq 0) + { + return $null + } + + # Switch OS architecture + switch -wildcard ($Architecture) + { + '*64*' + { + $Architecture = '64' + } + '*86*' + { + $Architecture = '32' + } + } + + # if there are multiple links then narrow down to the proper arc and os (if needed) + if ($Links.Count -gt 0) + { + # Second array of links to hold only the ones we want to target + $MatchingLink = @() + $MatchingLink.clear() + + foreach ($Link in $Links) + { + if ($Link -like "*w$($OS)$($Architecture)_*" -or $Link -like "*w$($OS)_$($Architecture)*") + { + $MatchingLink += $Link + } + } + } + } + + end + { + if ($MatchingLink) + { + return $MatchingLink + } + else + { + return 'badLink' + } + } + } + + function Get-RedirectedUrl + { + <# + .SYNOPSIS + Describe purpose of "Get-RedirectedUrl" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER URL + Describe parameter -URL. + + .EXAMPLE + Get-RedirectedUrl -URL Value + Describe what this call does + + .NOTES + Place additional notes here. + #> + [CmdletBinding(ConfirmImpact = 'None')] + param ( + [Parameter(Mandatory, HelpMessage = 'Add help message for user')] + [String] + $URL + ) + + process + { + $Request = [Net.WebRequest]::Create($URL) + $Request.AllowAutoRedirect = $false + $Request.Timeout = 3000 + $Response = $Request.GetResponse() + + if ($Response.ResponseUri) + { + $Response.GetResponseHeader('Location') + } + } + + end + { + $Response.Close() + } + } + + function LenovoModelTypeFinder + { + <# + .SYNOPSIS + Describe purpose of "LenovoModelTypeFinder" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER ComputerModel + Describe parameter -ComputerModel. + + .PARAMETER OS + Describe parameter -OS. + + .PARAMETER ComputerModelType + Describe parameter -ComputerModelType. + + .EXAMPLE + LenovoModelTypeFinder -ComputerModel Value -OS Value -ComputerModelType Value + Describe what this call does + + .NOTES + Place additional notes here. + #> + [CmdletBinding(ConfirmImpact = 'None')] + param ( + [string] + $ComputerModel, + [string] + $OS, + [string] + $ComputerModelType + ) + + process + { + try + { + if (-not ($LenovoModelDrivers)) + { + [xml]$script:LenovoModelXML = (Invoke-WebRequest -Uri $LenovoXMLSource -ErrorAction Stop) + + # Read Web Site + Write-CMLogEntry -Value "Info: Reading driver pack URL - $LenovoXMLSource" -Severity 1 + + # Set XML Object + $null = ($LenovoModelXML.GetType().FullName) + $script:LenovoModelDrivers = $LenovoModelXML.Products + } + } + catch + { + Write-CMLogEntry -Value "Error: $($_.Exception.Message)" -Severity 3 + } + + if ($ComputerModel.Length -gt 0) + { + $script:LenovoModelType = ($LenovoModelDrivers.Product | Where-Object { + $_.Queries.Version -match "$ComputerModel" + }).Queries.Types | Select-Object -ExpandProperty Type | Select-Object -First 1 + $script:LenovoSystemSKU = ($LenovoModelDrivers.Product | Where-Object { + $_.Queries.Version -match "$ComputerModel" + }).Queries.Types | Select-Object -ExpandProperty Type | Get-Unique + } + + if ($ComputerModelType.Length -gt 0) + { + $script:LenovoModelType = (($LenovoModelDrivers.Product.Queries) | Where-Object { + ($_.Types | Select-Object -ExpandProperty Type) -match $ComputerModelType + }).Version | Select-Object -First 1 + } + } + + end + { + return $LenovoModelType + } + } + + function InitiateDownloads + { + <# + .SYNOPSIS + Describe purpose of "InitiateDownloads" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .EXAMPLE + InitiateDownloads + Describe what this call does + + .NOTES + Place additional notes here. + #> + [CmdletBinding(ConfirmImpact = 'None')] + param () + + begin + { + $Product = 'Intune Driver Automation' + } + + process + { + # Driver Download ScriptBlock + $DriverDownloadJob = { + [CmdletBinding()] + param ([string] + $TempDirectory, + [string] + $ComputerModel, + [string] + $DriverCab, + [string] + $DriverDownloadURL + ) + + try + { + # Start Driver Download + $null = (Start-BitsTransfer -DisplayName "$ComputerModel-DriverDownload" -Source $DriverDownloadURL -Destination "$($TempDirectory + '\Driver Cab\' + $DriverCab)" -ErrorAction Stop) + } + catch + { + Write-CMLogEntry -Value "Error: $($_.Exception.Message)" -Severity 3 + } + } + + # Operating System Version + $OperatingSystem = ('Windows ' + $($WindowsVersion)) + + Write-CMLogEntry -Value '======== Starting Download Processes ========' -Severity 1 + Write-CMLogEntry -Value "Info: Operating System specified: Windows $OperatingSystem" -Severity 1 + Write-CMLogEntry -Value "Info: Operating System architecture specified: $($OSArchitecture)" -Severity 1 + + # Vendor Make + if ($ComputerModel) + { + $ComputerModel = $ComputerModel.Trim() + } + else + { + $ComputerModel = '' + } + + # Get Windows Version Number + switch -Wildcard ((Get-WmiObject -Class Win32_OperatingSystem).Version) + { + '*10.0.16*' + { + $OSBuild = '1709' + } + '*10.0.15*' + { + $OSBuild = '1703' + } + '*10.0.14*' + { + $OSBuild = '1607' + } + } + + Write-CMLogEntry -Value "Info: Windows 10 build $OSBuild identified for driver match" -Severity 1 + Write-CMLogEntry -Value "Info: Starting Download,Extract And Import Processes For $ComputerManufacturer Model: $($ComputerModel)" -Severity 1 + + if ($ComputerManufacturer -eq 'Dell') + { + Write-CMLogEntry -Value 'Info: Setting Dell variables' -Severity 1 + + if (-not ($DellModelCabFiles)) + { + [xml]$DellModelXML = (Get-Content -Path $TempDirectory\$DellXMLFile) + # Set XML Object + $null = ($DellModelXML.GetType().FullName) + $DellModelCabFiles = $DellModelXML.driverpackmanifest.driverpackage + } + + if ($SystemSKU) + { + Write-CMLogEntry -Value "Info: SystemSKU value is present, attempting match based on SKU - $SystemSKU)" -Severity 1 + + $ComputerModelURL = $DellDownloadBase + '/' + ($DellModelCabFiles | Where-Object { + ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.SystemID -eq $SystemSKU) + }).delta + $ComputerModelURL = $ComputerModelURL.Replace('\', '/') + $DriverDownload = $DellDownloadBase + '/' + ($DellModelCabFiles | Where-Object { + ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.SystemID -eq $SystemSKU) + }).path + $DriverCab = (($DellModelCabFiles | Where-Object { + ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.SystemID -eq $SystemSKU) + }).path).Split('/') | Select-Object -Last 1 + } + elseif ((-not ($SystemSKU)) -or (-not ($DriverCab))) + { + Write-CMLogEntry -Value 'Info: Falling back to matching based on model name' -Severity 1 + + $ComputerModelURL = $DellDownloadBase + '/' + ($DellModelCabFiles | Where-Object { + ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.Name -like "*$ComputerModel*") + }).delta + $ComputerModelURL = $ComputerModelURL.Replace('\', '/') + $DriverDownload = $DellDownloadBase + '/' + ($DellModelCabFiles | Where-Object { + ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.Name -like "*$ComputerModel") + }).path + $DriverCab = (($DellModelCabFiles | Where-Object { + ((($_.SupportedOperatingSystems).OperatingSystem).osCode -like "*$WindowsVersion*") -and ($_.SupportedSystems.Brand.Model.Name -like "*$ComputerModel") + }).path).Split('/') | Select-Object -Last 1 + } + + $DriverRevision = (($DriverCab).Split('-')[2]).Trim('.cab') + $DellSystemSKU = ($DellModelCabFiles.supportedsystems.brand.model | Where-Object { + $_.Name -match ('^' + $ComputerModel + '$') + } | Get-Unique).systemID + + if ($DellSystemSKU.count -gt 1) + { + $DellSystemSKU = [string]($DellSystemSKU -join ';') + } + + Write-CMLogEntry -Value "Info: Dell System Model ID is : $DellSystemSKU" -Severity 1 + } + + if ($ComputerManufacturer -eq 'Hewlett-Packard') + { + Write-CMLogEntry -Value 'Info: Setting HP variables' -Severity 1 + + if (-not ($HPModelSoftPaqs)) + { + [xml]$script:HPModelXML = (Get-Content -Path $TempDirectory\$HPXMLFile) + # Set XML Object + $null = ($HPModelXML.GetType().FullName) + $script:HPModelSoftPaqs = $HPModelXML.NewDataSet.HPClientDriverPackCatalog.ProductOSDriverPackList.ProductOSDriverPack + } + + if ($SystemSKU) + { + $HPSoftPaqSummary = $HPModelSoftPaqs | Where-Object { + ($_.SystemID -match $SystemSKU) -and ($_.OSName -like "$OSName*$OSArchitecture*$OSBuild*") + } | Sort-Object -Descending | Select-Object -First 1 + } + else + { + $HPSoftPaqSummary = $HPModelSoftPaqs | Where-Object { + ($_.SystemName -match $ComputerModel) -and ($_.OSName -like "$OSName*$OSArchitecture*$OSBuild*") + } | Sort-Object -Descending | Select-Object -First 1 + } + + if ($HPSoftPaqSummary) + { + $HPSoftPaq = $HPSoftPaqSummary.SoftPaqID + $HPSoftPaqDetails = $HPModelXML.newdataset.hpclientdriverpackcatalog.softpaqlist.softpaq | Where-Object { + $_.ID -eq "$HPSoftPaq" + } + $ComputerModelURL = $HPSoftPaqDetails.URL + $DriverDownload = ($HPSoftPaqDetails.URL).TrimStart('ftp:') + $DriverCab = $ComputerModelURL | Split-Path -Leaf + $DriverRevision = "$($HPSoftPaqDetails.Version)" + } + else + { + Write-CMLogEntry -Value 'Unsupported model / operating system combination found. Exiting.' -Severity 3 + exit 1 + } + } + + if ($ComputerManufacturer -eq 'Lenovo') + { + Write-CMLogEntry -Value 'Info: Setting Lenovo variables' -Severity 1 + + $script:LenovoModelType = (LenovoModelTypeFinder -ComputerModel $ComputerModel -OS $WindowsVersion) + + Write-CMLogEntry -Value "Info: $ComputerManufacturer $ComputerModel matching model type: $LenovoModelType" -Severity 1 + + if ($LenovoModelDrivers) + { + [xml]$script:LenovoModelXML = (New-Object -TypeName System.Net.WebClient).DownloadString("$LenovoXMLSource") + # Set XML Object + $null = ($LenovoModelXML.GetType().FullName) + $script:LenovoModelDrivers = $LenovoModelXML.Products + + if ($SystemSKU) + { + $ComputerModelURL = (($LenovoModelDrivers.Product | Where-Object { + ($_.Queries.smbios -match $SystemSKU -and $_.OS -match $WindowsVersion) + }).driverPack | Where-Object { + $_.id -eq 'SCCM' + }).'#text' + } + else + { + $ComputerModelURL = (($LenovoModelDrivers.Product | Where-Object { + ($_.Queries.Version -match ('^' + $ComputerModel + '$') -and $_.OS -match $WindowsVersion) + }).driverPack | Where-Object { + $_.id -eq 'SCCM' + }).'#text' + } + + Write-CMLogEntry -Value "Info: Model URL determined as $ComputerModelURL" -Severity 1 + + $DriverDownload = (FindLenovoDriver -URI $ComputerModelURL -os $WindowsVersion -Architecture $OSArchitecture) + + if ($DriverDownload) + { + $DriverCab = $DriverDownload | Split-Path -Leaf + $DriverRevision = ($DriverCab.Split('_') | Select-Object -Last 1).Trim('.exe') + + Write-CMLogEntry -Value "Info: Driver cabinet download determined as $DriverDownload" -Severity 1 + } + else + { + Write-CMLogEntry -Value "Error: Unable to find driver for $ComputerManufacturer $ComputerModel" -Severity 1 + } + } + } + + # Driver location variables + $DriverSourceCab = ($TempDirectory + '\Driver Cab\' + $DriverCab) + $DriverExtractDest = ("$TempDirectory" + '\Driver Files') + + Write-CMLogEntry -Value "Info: Driver extract location set - $DriverExtractDest" -Severity 1 + Write-CMLogEntry -Value "======== $Product - $ComputerManufacturer $ComputerModel DRIVER PROCESSING STARTED ========" -Severity 1 + Write-CMLogEntry -Value "$($Product): Retrieving ConfigMgr driver pack site For $ComputerManufacturer $ComputerModel" -Severity 1 + Write-CMLogEntry -Value "$($Product): URL found: $ComputerModelURL" -Severity 1 + + if (($ComputerModelURL) -and ($DriverDownload -ne 'badLink')) + { + # Cater for HP / Model Issue + $ComputerModel = $ComputerModel -replace '/', '-' + $ComputerModel = $ComputerModel.Trim() + Set-Location -Path $TempDirectory + + # Check for destination directory, create if required and download the driver cab + if (-not (Test-Path -Path $($TempDirectory + '\Driver Cab\' + $DriverCab))) + { + if (-not (Test-Path -Path $($TempDirectory + '\Driver Cab'))) + { + $null = (New-Item -ItemType Directory -Path $($TempDirectory + '\Driver Cab') -Force) + } + + Write-CMLogEntry -Value "$($Product): Downloading $DriverCab driver cab file" -Severity 1 + Write-CMLogEntry -Value "$($Product): Downloading from URL: $DriverDownload" -Severity 1 + + $null = (Start-Job -Name "$ComputerModel-DriverDownload" -ScriptBlock $DriverDownloadJob -ArgumentList ($TempDirectory, $ComputerModel, $DriverCab, $DriverDownload)) + Start-Sleep -Seconds 5 + + $BitsJob = Get-BitsTransfer | Where-Object { + $_.DisplayName -match "$ComputerModel-DriverDownload" + } + while (($BitsJob).JobState -eq 'Connecting') + { + Write-CMLogEntry -Value "$($Product): Establishing connection to $DriverDownload" -Severity 1 + + Start-Sleep -Seconds 30 + } + while (($BitsJob).JobState -eq 'Transferring') + { + if ($BitsJob.BytesTotal) + { + $PercentComplete = [int](($BitsJob.BytesTransferred * 100) / $BitsJob.BytesTotal) + + + Write-CMLogEntry -Value "$($Product): Downloaded $([int]((($BitsJob).BytesTransferred)/ 1MB)) MB of $([int]((($BitsJob).BytesTotal)/ 1MB)) MB ($PercentComplete%). Next update in 30 seconds." -Severity 1 + + Start-Sleep -Seconds 30 + } + else + { + Write-CMLogEntry -Value "$($Product): Download issues detected. Cancelling download process" -Severity 2 + + $null = (Get-BitsTransfer | Where-Object { + $_.DisplayName -eq "$ComputerModel-DriverDownload" + } | Remove-BitsTransfer) + } + } + + $null = (Get-BitsTransfer | Where-Object { + $_.DisplayName -eq "$ComputerModel-DriverDownload" + } | Complete-BitsTransfer) + + Write-CMLogEntry -Value "$($Product): Driver revision: $DriverRevision" -Severity 1 + } + else + { + Write-CMLogEntry -Value "$($Product): Skipping $DriverCab. Driver pack already downloaded." -Severity 1 + } + + # Cater for HP / Model Issue + $ComputerModel = $ComputerModel -replace '/', '-' + + if (((Test-Path -Path "$($TempDirectory + '\Driver Cab\' + $DriverCab)") -eq $true) -and ($DriverCab)) + { + Write-CMLogEntry -Value "$($Product): $DriverCab File exists - Starting driver update process" -Severity 1 + + if ((Test-Path -Path "$DriverExtractDest" -ErrorAction SilentlyContinue) -eq $false) + { + $null = (New-Item -ItemType Directory -Path "$($DriverExtractDest)" -Force) + } + + if ((Get-ChildItem -Path "$DriverExtractDest" -Recurse -Filter *.inf -File -ErrorAction SilentlyContinue).Count -eq 0) + { + Write-CMLogEntry -Value "==================== $Product DRIVER EXTRACT ====================" -Severity 1 + Write-CMLogEntry -Value "$($Product): Expanding driver CAB source file: $DriverCab" -Severity 1 + Write-CMLogEntry -Value "$($Product): Driver CAB destination directory: $DriverExtractDest" -Severity 1 + + if ($ComputerManufacturer -eq 'Dell') + { + Write-CMLogEntry -Value "$($Product): Extracting $ComputerManufacturer drivers to $DriverExtractDest" -Severity 1 + + $null = (& "$env:windir\system32\expand.exe" "$DriverSourceCab" -F:* "$DriverExtractDest") + } + if ($ComputerManufacturer -eq 'Hewlett-Packard') + { + Write-CMLogEntry -Value "$($Product): Extracting $ComputerManufacturer drivers to $DriverExtractDest" -Severity 1 + + # Driver Silent Extract Switches + $HPSilentSwitches = ('/s /e /f "' + $DriverExtractDest + '"') + + Write-CMLogEntry -Value "$($Product): Using $ComputerManufacturer silent switches: $HPSilentSwitches" -Severity 1 + + $null = (Start-Process -FilePath "$($TempDirectory + '\Driver Cab\' + $DriverCab)" -ArgumentList $HPSilentSwitches -Verb RunAs) + $DriverProcess = ($DriverCab).Substring(0, $DriverCab.length - 4) + + # Wait for HP SoftPaq Process To Finish + while ((Get-Process).name -contains $DriverProcess) + { + Write-CMLogEntry -Value "$($Product): Waiting for extract process (Process: $DriverProcess) to complete.. Next check in 30 seconds" -Severity 1 + + Start-Sleep -Seconds 30 + } + } + if ($ComputerManufacturer -eq 'Lenovo') + { + # Driver Silent Extract Switches + $script:LenovoSilentSwitches = ('/VERYSILENT /DIR=' + '"' + $DriverExtractDest + '"' + ' /Extract="Yes"') + + Write-CMLogEntry -Value "$($Product): Using $ComputerManufacturer silent switches: $LenovoSilentSwitches" -Severity 1 + Write-CMLogEntry -Value "$($Product): Extracting $ComputerManufacturer drivers to $DriverExtractDest" -Severity 1 + + $null = (Unblock-File -Path $($TempDirectory + '\Driver Cab\' + $DriverCab)) + $null = (Start-Process -FilePath "$($TempDirectory + '\Driver Cab\' + $DriverCab)" -ArgumentList $LenovoSilentSwitches -Verb RunAs) + + $DriverProcess = ($DriverCab).Substring(0, $DriverCab.length - 4) + + # Wait for Lenovo Driver Process To Finish + while ((Get-Process).name -contains $DriverProcess) + { + Write-CMLogEntry -Value "$($Product): Waiting for extract process (Process: $DriverProcess) to complete.. Next check in 30 seconds" -Severity 1 + + Start-Sleep -Seconds 30 + } + } + } + else + { + Write-CMLogEntry -Value 'Skipping. Drivers already extracted.' -Severity 1 + } + } + else + { + Write-CMLogEntry -Value "$($Product): $DriverCab file download failed" -Severity 3 + } + } + elseif ($DriverDownload -eq 'badLink') + { + Write-CMLogEntry -Value "$($Product): Operating system driver package download path not found.. Skipping $ComputerModel" -Severity 3 + } + else + { + Write-CMLogEntry -Value "$($Product): Driver package not found for $ComputerModel running Windows $WindowsVersion $OSArchitecture. Skipping $ComputerModel" -Severity 2 + } + + Write-CMLogEntry -Value "======== $Product - $ComputerManufacturer $ComputerModel DRIVER PROCESSING FINISHED ========" -Severity 1 + } + } + + function Update-Drivers + { + <# + .SYNOPSIS + Describe purpose of "Update-Drivers" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .EXAMPLE + Update-Drivers + Describe what this call does + + .NOTES + Place additional notes here. + #> + [CmdletBinding(ConfirmImpact = 'None')] + param () + + begin + { + $DriverPackagePath = (Join-Path -Path $TempDirectory -ChildPath 'Driver Files') + + Write-CMLogEntry -Value "Driver package location is $DriverPackagePath" -Severity 1 + Write-CMLogEntry -Value 'Starting driver installation process' -Severity 1 + Write-CMLogEntry -Value "Reading drivers from $DriverPackagePath" -Severity 1 + } + + process + { + # Apply driver maintenance package + try + { + if ((Get-ChildItem -Path $DriverPackagePath -Filter *.inf -Recurse).count -gt 0) + { + try + { + $null = (Start-Process -FilePath 'powershell.exe' -WorkingDirectory $DriverPackagePath -ArgumentList "pnputil /add-driver *.inf /subdirs /install | Out-File -FilePath (Join-Path $LogDirectory '\Install-Drivers.txt') -Append" -NoNewWindow -Wait) + + Write-CMLogEntry -Value 'Driver installation complete. Restart required' -Severity 1 + } + catch + { + Write-CMLogEntry -Value "An error occurred while attempting to apply the driver maintenance package. Error message: $($_.Exception.Message)" -Severity 3 + + exit 1 + } + } + else + { + Write-CMLogEntry -Value "No driver inf files found in $DriverPackagePath." -Severity 3 + + exit 1 + } + } + catch + { + Write-CMLogEntry -Value "An error occurred while attempting to apply the driver maintenance package. Error message: $($_.Exception.Message)" -Severity 3 + + exit 1 + } + + Write-CMLogEntry -Value 'Finished driver maintenance.' -Severity 1 + } + + end + { + return $LastExitCode + } + } +} + +process +{ + if ($OSName -eq 'Windows 10') + { + # Download manufacturer lists for driver matching + $null = (DownloadDriverList) + + # Initiate matched downloads + $null = (InitiateDownloads) + + # Update driver repository and install drivers + (Update-Drivers -ErrorAction Stop) + } + else + { + Write-CMLogEntry -Value 'An upsupported OS was detected. This script only supports Windows 10.' -Severity 3 + + exit 1 + } +} + +end +{ + $null = (Pop-Location) + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-OptimizeAppsForTerminalService.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-OptimizeAppsForTerminalService.ps1 new file mode 100644 index 0000000..23d8b3e --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-OptimizeAppsForTerminalService.ps1 @@ -0,0 +1,323 @@ +#requires -Version 3.0 -Modules BitsTransfer -RunAsAdministrator + +<# + .SYNOPSIS + Download, install, and Tweak System and Apps for Terminal Server use + + .DESCRIPTION + Download, install, and Tweak System and Apps for Terminal Server (WVD/VDI/WDS) use + + .NOTES + Early testing release - Future releases might get some parameters + + Changelog: + 1.0.1: Reformatted + 1.0.0: Initial Release + + Version 1.0.1 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Download, install, and Tweak System and Apps for Terminal Server use' + + # Default URL (Assume we use 64Bit) + [string]$FSLogixUrl = 'https://aka.ms/fslogix_download' + + #region PossibleParameters + # Where to Store it + [string]$Target = ($env:Temp) + + # File Name + [string]$TargetName = 'fslogix.zip' + + # Install Switch + [string]$Arguments = '/install /quiet /norestart' + #endregion PossibleParameters + + #region Defaults + # Set the full path of the downloaded installer + [string]$InstallerPackage = ($Target + '\' + $TargetName) + + [string]$InstallerDestination = (($InstallerPackage).Replace('.zip', '')) + [string]$InstallerExecutable = ($InstallerDestination + '\x64\Release\FSLogixAppsSetup.exe') + $SCT = 'SilentlyContinue' + $STP = 'Stop' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } +} + +process +{ + Write-Verbose -Message ('Downloading {0} to {1}' -f $TargetName, $InstallerPackage) + + # Use BitsTransfer to download the latest installer + $paramStartBitsTransfer = @{ + Source = $FSLogixUrl + Destination = $InstallerPackage + Priority = 'Foreground' + TransferPolicy = 'Always' + ErrorAction = $STP + } + $null = (Start-BitsTransfer @paramStartBitsTransfer) + + # Expand FSLogix Installer + $paramTestPath = @{ + Path = $InstallerPackage + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramTestPath = @{ + Path = $InstallerDestination + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $InstallerDestination + Force = $true + Confirm = $false + ItemType = 'Directory' + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + try + { + # Expand-Archive is to buggy! + $paramAddType = @{ + AssemblyName = 'System.IO.Compression.FileSystem' + ErrorAction = $STP + } + $null = (Add-Type @paramAddType) + $null = ([IO.Compression.ZipFile]::ExtractToDirectory($InstallerPackage, $InstallerDestination)) + } + catch + { + # OK! That is crappy, but it still works well as a fallback. + $paramNewObject = @{ + ComObject = 'Shell.Application' + ErrorAction = $STP + } + $shellApp = (New-Object @paramNewObject) + $shellZip = $shellApp.NameSpace([String]$InstallerPackage) + $shellDest = $shellApp.NameSpace($InstallerDestination) + $shellDest.CopyHere($shellZip.items()) + } + } + else + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # We are done + break + } + + # Install FSLogix + $paramTestPath = @{ + Path = $InstallerExecutable + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $InstallerExecutable + ErrorAction = $SCT + } + $InstallerVersion = ((Get-ItemProperty @paramGetItemProperty).VersionInfo.ProductVersion) + + Write-Verbose -Message ('Running FSLogix installer version {0}' -f $InstallerVersion) + + $paramStartProcess = @{ + FilePath = $InstallerExecutable + ArgumentList = $Arguments + Wait = $true + PassThru = $true + ErrorAction = $STP + } + $InstallerProcess = (Start-Process @paramStartProcess) + + if (($InstallerProcess | Select-Object -ExpandProperty ExitCode) -eq 0) + { + Write-Verbose -Message ('Installed FSLogix version {0}' -f $InstallerVersion) + } + else + { + Write-Warning -Message ('Installer exit code {0}.' -f $InstallerProcess.ExitCode) + } + + Write-Verbose -Message ('Removing file: {0}' -f $InstallerPackage) + + # Remove the downloaded Installaer Package + $paramRemoveItem = @{ + Path = $InstallerPackage + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + + # Install the expanded stuff + $paramRemoveItem = @{ + Path = $InstallerDestination + Recurse = $true + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + + # Legacy HKLM Path for WVD/VDI/WDS Environment + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Citrix\PortICA' + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Ensure that the registry path exists + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Teams' + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Tell Microsoft Teams that it runs in an WVD/VDI/WDS Environment + # Source: https://docs.microsoft.com/en-us/azure/virtual-desktop/teams-on-wvd + $paramNewItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Teams' + Name = 'IsWVDEnvironment' + PropertyType = 'DWORD' + Value = 1 + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + + # Ensure that the registry path exists + $paramNewItem = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32' + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + + # Do not start Microsoft Teams after Login + $paramNewItemProperty = @{ + Path = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32' + Name = 'Teams' + PropertyType = 'Binary' + Value = ([byte[]](0x01, 0x00, 0x00, 0x00, 0x1a, 0x19, 0xc3, 0xb9, 0x62, 0x69, 0xd5, 0x01)) + Confirm = $false + Force = $true + ErrorAction = $SCT + } + $null = (New-ItemProperty @paramNewItemProperty) + } + else + { + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = [PSCustomObject]@{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # output information. Post-process collected info, and log info (optional) + $info | Out-String | Write-Verbose + + $paramWriteError = @{ + Message = $e.Exception.Message + ErrorAction = $STP + Exception = $e.Exception + TargetObject = $e.CategoryInfo.TargetName + } + Write-Error @paramWriteError + + # We are done + break + } +} + +end +{ + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakScheduledTask.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakScheduledTask.ps1 new file mode 100644 index 0000000..0ea5dcc --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakScheduledTask.ps1 @@ -0,0 +1,127 @@ +#requires -Version 2.0 -Modules ScheduledTasks + +<# + .SYNOPSIS + Cleanup some scheduled tasks + + .DESCRIPTION + Cleanup some scheduled tasks, mostly auto update related + + .NOTES + The Auto updates are great! But we use Choco and our own solution to deploy updates. + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Cleanup some scheduled tasks' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults +} + +process +{ + # Disable the Brave (Browser) Updater Tasks + $paramGetScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $paramDisableScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-ScheduledTask @paramGetScheduledTask | Where-Object -FilterScript { + (($_.TaskName -like 'BraveSoftwareUpdateTask*') -and ($_.State -ne 'Disabled')) + } | Disable-ScheduledTask @paramDisableScheduledTask) + + # Disable the Google Chrome (Browser) Updater Tasks + $paramGetScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $paramDisableScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-ScheduledTask @paramGetScheduledTask | Where-Object -FilterScript { + (($_.TaskName -like 'GoogleUpdateTaskMachine*') -and ($_.State -ne 'Disabled')) + } | Disable-ScheduledTask @paramDisableScheduledTask) + + <# + # Disable the Microsoft Chromium Edge (Browser) Updater Tasks + $paramGetScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $paramDisableScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-ScheduledTask @paramGetScheduledTask | Where-Object -FilterScript { + (($_.TaskName -like 'MicrosoftEdgeUpdateTaskMachine*') -and ($_.State -ne 'Disabled')) + } | Disable-ScheduledTask @paramDisableScheduledTask) + #> + + # Disable the HP WarrantyChecker Tasks + $paramGetScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $paramDisableScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-ScheduledTask @paramGetScheduledTask | Where-Object -FilterScript { + (($_.TaskName -like 'WarrantyChecker*') -and ($_.State -ne 'Disabled')) + } | Disable-ScheduledTask @paramDisableScheduledTask) + + # Disable the Firefox Default Browser Agent Tasks + $paramGetScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $paramDisableScheduledTask = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-ScheduledTask @paramGetScheduledTask | Where-Object -FilterScript { + (($_.TaskName -like 'Firefox Default Browser Agent*') -and ($_.State -ne 'Disabled')) + } | Disable-ScheduledTask @paramDisableScheduledTask) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakService.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakService.ps1 new file mode 100644 index 0000000..1586d28 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakService.ps1 @@ -0,0 +1,96 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Disable some Services + + .DESCRIPTION + Disable some Services, mostly auto update related + + .NOTES + The Auto updates are great! But we use Choco and our own solution to deploy updates. + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Disable some Services' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + $DisableServices = @( + #'edgeupdate' + #'edgeupdatem' + 'gupdate' + 'gupdatem' + ) +} + +process +{ + foreach ($DisableService in $DisableServices) + { + # Get the Given Service + $paramGetService = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + $DisableServiceInfo = ($DisableService | Get-Service @paramGetService) + + # Stop the given Service + $paramStopService = @{ + Force = $true + NoWait = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = ($DisableServiceInfo | Stop-Service @paramStopService) + + # Disable the given Service + $paramSetService = @{ + StartupType = 'Manual' + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = ($DisableServiceInfo | Set-Service @paramSetService) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakSystemAutoStartApps.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakSystemAutoStartApps.ps1 new file mode 100644 index 0000000..96133df --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakSystemAutoStartApps.ps1 @@ -0,0 +1,102 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Disable some System Auto Starts + + .DESCRIPTION + Disable some System Auto Starts to save some memory and CPU resources + + .NOTES + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Disable some System Auto Starts' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + $DisableAutoPathList = @( + 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run' + 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32' + 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\StartupFolder' + ) + + $DisableAutoStarts = @( + 'KeePassXC' + 'KeePass' + 'KeePass 2 PreLoad' + '1Password' + 'BraveSoftware Update' + ) +} + +process +{ + foreach ($item in $DisableAutoStarts) + { + foreach ($DisableAutoPath in $DisableAutoPathList) + { + $AutoStartStatus = $null + + $paramGetItemProperty = @{ + Path = $DisableAutoPath + Name = $item + ErrorAction = $SCT + WarningAction = $SCT + } + $AutoStartStatus = (Get-ItemProperty @paramGetItemProperty) + + if ($AutoStartStatus) + { + $paramSetItemProperty = @{ + Path = $DisableAutoPath + Name = $item + Value = ([byte[]](0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakTeamsClientFirewall.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakTeamsClientFirewall.ps1 new file mode 100644 index 0000000..3642704 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakTeamsClientFirewall.ps1 @@ -0,0 +1,138 @@ +#requires -Version 3.0 -Modules NetSecurity -RunAsAdministrator + +<# + .SYNOPSIS + Tweak the Firewall Rules for Microsoft Teams clients + + .DESCRIPTION + Tweak the Firewall Rules for Microsoft Teams clients for all users that have it installed + + .NOTES + Early testing release + + Changelog: + 1.0.1: Reformatted + 1.0.0: Initial Release + + Version 1.0.1 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Tweak the Firewall Rules for Microsoft Teams clients for all users that have it installed' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults +} + +process +{ + # Creates firewall rules for Microsoft Teams + $AllUsers = $null + + $paramJoinPath = @{ + Path = $env:SystemDrive + ChildPath = 'Users' + ErrorAction = $SCT + } + $paramGetChildItem = @{ + Path = (Join-Path @paramJoinPath) + ErrorAction = $SCT + Exclude = 'Public', 'ADMINI~*' + } + $AllUsers = (Get-ChildItem @paramGetChildItem) + + if ($null -ne $AllUsers) + { + foreach ($SingleUser in $AllUsers) + { + # Cleanup + $FullTeamsPath = $null + + # get the Executable + $paramJoinPath = @{ + Path = $SingleUser.FullName + ChildPath = 'AppData\Local\Microsoft\Teams\Current\Teams.exe' + ErrorAction = $SCT + } + $FullTeamsPath = (Join-Path @paramJoinPath) + + $paramTestPath = @{ + Path = $FullTeamsPath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetNetFirewallApplicationFilter = @{ + Program = $FullTeamsPath + ErrorAction = $SCT + } + if (-not (Get-NetFirewallApplicationFilter @paramGetNetFirewallApplicationFilter)) + { + # Cleanup + $NetFirewallRuleName = $null + + # Apply the Rulename + $NetFirewallRuleName = ('Teams.exe for user {0}' -f $SingleUser.Name) + + 'UDP', 'TCP' | ForEach-Object -Process { + $paramNewNetFirewallRule = @{ + DisplayName = $NetFirewallRuleName + Direction = 'Inbound' + Profile = 'Any' + Program = $FullTeamsPath + Action = 'Allow' + Protocol = $_ + Enabled = 'True' + Confirm = $false + ErrorAction = $SCT + } + $null = (New-NetFirewallRule @paramNewNetFirewallRule) + } + + # Cleanup + $NetFirewallRuleName = $null + } + } + + # Cleanup + $FullTeamsPath = $null + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2020, Beyond Datacenter + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakUserAutoStartApps.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakUserAutoStartApps.ps1 new file mode 100644 index 0000000..4f4a52c --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Invoke-TweakUserAutoStartApps.ps1 @@ -0,0 +1,105 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Disable some User Auto Starts + + .DESCRIPTION + Disable some System Auto Starts to save some memory and CPU resources + + .NOTES + User can enable them again, if needed + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Disable some User Auto Starts' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + $DisableAutoPathList = @( + 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run' + 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\Run32' + 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\StartupApproved\StartupFolder' + ) + + $DisableAutoStarts = @( + 'KeePassXC' + 'KeePass' + 'KeePass 2 PreLoad' + '1Password' + 'BraveSoftware Update' + ) +} + +process +{ + foreach ($item in $DisableAutoStarts) + { + foreach ($DisableAutoPath in $DisableAutoPathList) + { + $AutoStartStatus = $null + + $paramGetItemProperty = @{ + Path = $DisableAutoPath + Name = $item + ErrorAction = $SCT + WarningAction = $SCT + } + + $AutoStartStatus = (Get-ItemProperty @paramGetItemProperty) + + if ($AutoStartStatus) + { + $paramSetItemProperty = @{ + Path = $DisableAutoPath + Name = $item + Value = ([byte[]](0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)) + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/NEW/Set-BSIRecommendedTelemetryMitigation.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/NEW/Set-BSIRecommendedTelemetryMitigation.ps1 new file mode 100644 index 0000000..f459fda --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/NEW/Set-BSIRecommendedTelemetryMitigation.ps1 @@ -0,0 +1,14 @@ +Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\ -name AllowTelemetry -Value 0 +Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection\ -name AllowTelemetry + +Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\DiagTrack\ -name Start -Value 4 +Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\DiagTrack\ -name Start + +Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\WMI\Autologger\AutoLogger-Diagtrack-Listener\ -name Start -Value 0 +Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\WMI\Autologger\AutoLogger-Diagtrack-Listener\ -name Start + +Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv\ -name Start -Value 4 +Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\wuauserv\ -name Start + +New-NetFirewallRule -DisplayName "BlockDiagTrack" -Name "BlockDiagTrack" -Direction Outbound -Program "%SystemRoot%\System32\utc_myhost.exe" -Action Block + diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/New-PowerShellProfiles.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/New-PowerShellProfiles.ps1 new file mode 100644 index 0000000..c65ded9 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/New-PowerShellProfiles.ps1 @@ -0,0 +1,161 @@ +#requires -Version 1.0 -RunAsAdministrator + +<# + .SYNOPSIS + Create plain PowerShell Profiles, if needed + + .DESCRIPTION + Create plain PowerShell Profiles, if needed + + .NOTES + Changelog: + 1.0.5: Reformatted: + 1.0.1: First real release + 1.0.0: Initial beta version + + Version 1.0.1 + + .LINK + http://beyend-datacenter.com + + .LINK + https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles?view=powershell-7 + + .LINK + https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_profiles?view=powershell-5.1 +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Create plain PowerShell Profiles, if needed' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) +} + +process +{ + # Stop Search - Gain performance + $null = (Get-Service -Name 'WSearch' -ErrorAction $SCT | Where-Object { $_.Status -eq 'Running' } | Stop-Service -Force -Confirm:$false -ErrorAction $SCT) + + # Splat the parameters + $paramNewItem = @{ + type = 'file' + force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + + # Splat the parameters + $paramTestPath = @{ + ErrorAction = $SCT + WarningAction = $SCT + } + + if (-not (Test-Path -Path $PROFILE @paramTestPath)) + { + $null = (New-Item -Path $PROFILE @paramNewItem) + } + + if (-not (Test-Path -Path $PROFILE.AllUsersAllHosts @paramTestPath)) + { + $null = (New-Item -Path $PROFILE.AllUsersAllHosts @paramNewItem) + } + + if (-not (Test-Path -Path $PROFILE.AllUsersCurrentHost @paramTestPath)) + { + $null = (New-Item -Path $PROFILE.AllUsersCurrentHost @paramNewItem) + } + + if (-not (Test-Path -Path $PROFILE.CurrentUserAllHosts @paramTestPath)) + { + $null = (New-Item -Path $PROFILE.CurrentUserAllHosts @paramNewItem) + } + + if (-not (Test-Path -Path $PROFILE.CurrentUserCurrentHost @paramTestPath)) + { + $null = (New-Item -Path $PROFILE.CurrentUserCurrentHost @paramNewItem) + } + + #region ISE + $ISEProfileAllUsersCurrentHost = ($PsHome + '\Microsoft.PowerShellISE_profile.ps1') + if (-not (Test-Path -Path $ISEProfileAllUsersCurrentHost @paramTestPath)) + { + $null = (New-Item -Path $ISEProfileAllUsersCurrentHost @paramNewItem) + } + + $ISEProfileCurrentUserAllHosts = ($Home + '\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1') + if (-not (Test-Path -Path $ISEProfileCurrentUserAllHosts @paramTestPath)) + { + $null = (New-Item -Path $ISEProfileCurrentUserAllHosts @paramNewItem) + } + #endregion ISE + + #region VSCode + $VSCodeProfileAllUsersCurrentHost = ($PSHOME + '\Microsoft.VSCode_profile.ps1') + if (-not (Test-Path -Path $VSCodeProfileAllUsersCurrentHost @paramTestPath)) + { + $null = (New-Item -Path $VSCodeProfileAllUsersCurrentHost @paramNewItem) + } + + $VSCodeProfileCurrentUserAllHosts = ($Home + '\Documents\PowerShell\Microsoft.VSCode_profile.ps1') + if (-not (Test-Path -Path $VSCodeProfileCurrentUserAllHosts @paramTestPath)) + { + $null = (New-Item -Path $VSCodeProfileCurrentUserAllHosts @paramNewItem) + } + #endregion VSCode + + #region PowerShellCore + $PSCoreCurrentUserAllHosts = ($Home + '\Documents\PowerShell\profile.ps1') + if (-not (Test-Path -Path $PSCoreCurrentUserAllHosts @paramTestPath)) + { + $null = (New-Item -Path $PSCoreCurrentUserAllHosts @paramNewItem) + } + + $PSCoreCurrentUserCurrentHost = ($Home + '\Documents\PowerShell\Microsoft.PowerShell_profile.ps1') + if (-not (Test-Path -Path $PSCoreCurrentUserCurrentHost @paramTestPath)) + { + $null = (New-Item -Path $PSCoreCurrentUserCurrentHost @paramNewItem) + } + #endregion PowerShellCore +} + +end +{ + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + #> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/New-ScheduledChocoUpdateTaks.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/New-ScheduledChocoUpdateTaks.ps1 new file mode 100644 index 0000000..ff86684 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/New-ScheduledChocoUpdateTaks.ps1 @@ -0,0 +1,148 @@ +#requires -Version 2.0 -Modules ScheduledTasks + +<# + .SYNOPSIS + Creates a Scheduled Task to keep all Chocolatey Packages up-to-date + + .DESCRIPTION + Creates a Scheduled Task to keep all Chocolatey Packages up-to-date, it runs each time a user logs in to this system + + .NOTES + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Creates a Scheduled Task to keep all Chocolatey Packages up-to-date' + + #region Defaults + $STP = 'Stop' + $SCT = 'SilentlyContinue' + #endregion Defaults + + # Define the Name + $ScheduledTaskName = 'Run Choco Upgrade at Login' + + # Define the description as string + $ScheduledTaskDescription = 'Scheduled Task to keep all Chocolatey Packages up-to-date' + + # See if choco.exe is available. If not, stop execution + $paramGetCommand = @{ + Name = 'choco.exe' + ErrorAction = $SCT + WarningAction = $SCT + } + $chocoCmd = (Get-Command @paramGetCommand | Select-Object -ExpandProperty Source) +} + +process +{ + try + { + if (-not ($chocoCmd)) + { + Write-Error -Message 'Chocolatey executable not found' -ErrorAction $STP + } + else + { + $paramGetScheduledTask = @{ + TaskName = $ScheduledTaskName + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-ScheduledTask @paramGetScheduledTask | Unregister-ScheduledTask -Confirm:$false -ErrorAction $SCT) + + # What to execute + $paramNewScheduledTaskAction = @{ + Execute = $chocoCmd + Argument = 'upgrade all -y >NUL 2>&1' + ErrorAction = $STP + } + $taskAction = (New-ScheduledTaskAction @paramNewScheduledTaskAction) + + # Trigegr when someone login + $paramNewScheduledTaskTrigger = @{ + AtLogOn = $true + ErrorAction = $STP + } + $taskTrigger = (New-ScheduledTaskTrigger @paramNewScheduledTaskTrigger) + + # Delay the Task for one (1) minute + $taskTrigger.Delay = 'PT1M' + + # Who run the task and what run level to use (System and Highest + $paramNewScheduledTaskPrincipal = @{ + UserId = 'SYSTEM' + RunLevel = 'Highest' + ErrorAction = $STP + } + $taskUserPrincipal = (New-ScheduledTaskPrincipal @paramNewScheduledTaskPrincipal) + + # Win8 is the latest + $paramNewScheduledTaskSettingsSet = @{ + Compatibility = 'Win8' + ErrorAction = $STP + } + $taskSettings = (New-ScheduledTaskSettingsSet @paramNewScheduledTaskSettingsSet) + + # Set up the new task + $paramNewScheduledTask = @{ + Action = $taskAction + Principal = $taskUserPrincipal + Trigger = $taskTrigger + Settings = $taskSettings + Description = $ScheduledTaskDescription + ErrorAction = $STP + } + $task = (New-ScheduledTask @paramNewScheduledTask) + + # Register the new task + $paramRegisterScheduledTask = @{ + TaskName = $ScheduledTaskName + InputObject = $task + Force = $true + TaskPath = '\' + ErrorAction = $STP + } + $null = (Register-ScheduledTask @paramRegisterScheduledTask) + } + } + catch + { + Write-Error -Message 'Whoopsie' -ErrorAction $STP + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Optimize-MicrosoftDefenderExclusions.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Optimize-MicrosoftDefenderExclusions.ps1 new file mode 100644 index 0000000..e18caf1 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Optimize-MicrosoftDefenderExclusions.ps1 @@ -0,0 +1,473 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Apply the Defender exclusions based on recommendations by Microsoft + + .DESCRIPTION + Apply the Defender exclusions based on recommendations by Microsoft, + Some additional Controlled Folder Access Allowed Applications will be added as well + + .EXAMPLE + PS C:\> Optimize-MicrosoftDefenderExclusions.ps1 + + .NOTES + Do not just use set-mppreference here, this might remove any existing exclusions. + Might be the right thing to do, but with add-mppreference you append to the list (if exists). + + Changelog: + 1.0.4: Reformated + 1.0.3: Add ControlledFolderAccessAllowedApplications handling + 1.0.2: First real release + 1.0.0: Intital beta version + + Version 1.0.4 + + .LINK + http://enatec.io + + .LINK + https://support.microsoft.com/en-ie/help/822158/virus-scanning-recommendations-for-enterprise-computers-that-are-runni + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/add-mppreference + + .LINK + https://docs.microsoft.com/en-us/powershell/module/defender/set-mppreference +#> +[CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Apply the Defender exclusions based on recommendations by Microsoft' + + #region + $SCT = 'SilentlyContinue' + #endregion + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + #region DefaultExclusions + $ExcludePathList = @( + "$env:windir\SoftwareDistribution\DataStore\Datastore.edb", + "$env:windir\SoftwareDistribution\DataStore\Logs\Edb*.jrs", + "$env:windir\SoftwareDistribution\DataStore\Logs\Edb.chk", + "$env:windir\SoftwareDistribution\DataStore\Logs\Tmp.edb", + "$env:windir\Security\Database\*.edb", + "$env:windir\Security\Database\*.sdb", + "$env:windir\Security\Database\*.log", + "$env:windir\Security\Database\*.chk", + "$env:windir\Security\Database\*.jrs", + "$env:windir\Security\Database\*.xml", + "$env:windir\Security\Database\*.csv", + "$env:windir\Security\Database\*.cmtx", + "$env:windir\System32\GroupPolicy\Machine\Registry.pol", + "$env:windir\System32\GroupPolicy\Machine\Registry.tmp", + "$env:windir\System32\GroupPolicy\User\Registry.pol", + "$env:windir\System32\GroupPolicy\User\Registry.tmp", + "$env:ProgramData\ntuser.pol", + "$env:ProgramData\chocolatey\lib\sysinternals\tools\*.exe" + ) + #endregion DefaultExclusions + + #region AdExclusions + # Turn off scanning of Active Directory and Active Directory-related files + + # Exclude the Main NTDS database files. + $DSADatabaseFile = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' + $DSADatabaseFilePath = ('Registry::' + $DSADatabaseFile) + $paramTestPath = @{ + Path = $DSADatabaseFilePath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $DSADatabaseFilePath + ErrorAction = $SCT + } + $DSADatabaseFileValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'DSA Database file') + + if ($DSADatabaseFileValue) + { + $ExcludePathList += ($DSADatabaseFileValue) + $ExcludePathList += ($DSADatabaseFileValue).Replace('.dit', '.pat') + } + } + else + { + Write-Verbose -Message 'No NTDS database files to exclude' + } + + # Exclude the Active Directory transaction log files. + $DatabaseLogFiles = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' + $DatabaseLogFilesPath = ('Registry::' + $DatabaseLogFiles) + + $paramTestPath = @{ + Path = $DatabaseLogFilesPath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $DatabaseLogFilesPath + ErrorAction = $SCT + } + $DatabaseLogFilesPathValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'Database Log Files Path') + + if ($DatabaseLogFilesPathValue) + { + $ExcludePathList += ($DatabaseLogFilesPathValue + '\EDB*.log') + $ExcludePathList += ($DatabaseLogFilesPathValue + '\Res*.log') + $ExcludePathList += ($DatabaseLogFilesPathValue + '\Edb*.jrs') + $ExcludePathList += ($DatabaseLogFilesPathValue + '\Ntds.pat') + } + } + else + { + Write-Verbose -Message 'No Active Directory transaction log files to exclude' + } + + # Exclude the files in the NTDS Working folder + $DSAWorkingDir = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NTDS\Parameters' + $DSAWorkingDirPath = ('Registry::' + $DSAWorkingDir) + + $paramTestPath = @{ + Path = $DSAWorkingDirPath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $DSAWorkingDirPath + ErrorAction = $SCT + } + $DSAWorkingDirValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'DSA Working Directory') + + if ($DSAWorkingDirValue) + { + $ExcludePathList += ($DSAWorkingDirValue + '\Temp.edb') + $ExcludePathList += ($DSAWorkingDirValue + '\Edb.chk') + } + } + else + { + Write-Verbose -Message 'No NTDS Working folder to exclude' + } + #endregion AdExclusions + + #region SysVolExclusions + # Turn off scanning of SYSVOL files + + # Turn off scanning of files in the File Replication Service (FRS) Working folder + $SysVolWorkingDir = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\NtFrs\Parameters' + $SysVolWorkingDirPath = ('Registry::' + $SysVolWorkingDir) + + $paramTestPath = @{ + Path = $SysVolWorkingDirPath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $SysVolWorkingDirPath + ErrorAction = $SCT + } + $SysVolWorkingDirValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'Working Directory') + if ($SysVolWorkingDirValue) + { + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\sys\edb.chk') + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\Ntfrs.jdb') + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\log\*.log') + } + } + else + { + Write-Verbose -Message 'No File Replication Service Working folder to exclude' + } + + # Turn off scanning of files in the File Replication Service Database Log files + $SysVolDBLogFileDir = 'HKEY_LOCAL_MACHINE\SYSTEM\Currentcontrolset\Services\Ntfrs\Parameters' + $SysVolDBLogFileDirPath = ('Registry::' + $SysVolDBLogFileDir) + + if (Test-Path -Path $SysVolDBLogFileDirPath -ErrorAction $SCT) + { + $paramGetItemProperty = @{ + Path = $SysVolWorkingDirPath + ErrorAction = $SCT + } + $SysVolDBLogFileDirValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'Working Directory') + + if ($SysVolDBLogFileDirValue) + { + $ExcludePathList += ($SysVolDBLogFileDirValue + '\Jet\Log\Edb*.jrs') + } + else + { + if ($SysVolWorkingDirValue) + { + $ExcludePathList += ($SysVolWorkingDirValue + '\jet\Log\Edb*.log') + } + } + } + else + { + Write-Verbose -Message 'No File Replication Service Database Log files to exclude' + } + #endregion SysVolExclusions + + #region DhcpExclusions + # Turn off scanning of DHCP files + $DhcpFiles = 'HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\DHCPServer\Parameters' + $DhcpFilesPath = ('Registry::' + $DhcpFiles) + + $paramTestPath = @{ + Path = $DhcpFilesPath + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramGetItemProperty = @{ + Path = $DhcpFilesPath + ErrorAction = $SCT + } + $DhcpDatabasePathValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'DatabasePath') + if ($DhcpDatabasePathValue) + { + $ExcludePathList += ($DhcpDatabasePathValue + '\*.mdb') + $ExcludePathList += ($DhcpDatabasePathValue + '\*.pat') + $ExcludePathList += ($DhcpDatabasePathValue + '\*.chk') + $ExcludePathList += ($DhcpDatabasePathValue + '\*.edb') + } + + $paramGetItemProperty = @{ + Path = $DhcpFilesPath + ErrorAction = $SCT + } + $DhcpLogFilePathValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'DhcpLogFilePath') + + if (($DhcpLogFilePathValue) -and ($DhcpLogFilePathValue -ne $DhcpDatabasePathValue)) + { + $ExcludePathList += ($DhcpLogFilePathValue + '\*.log') + } + else + { + $ExcludePathList += ($DhcpDatabasePathValue + '\*.log') + } + + $paramGetItemProperty = @{ + Path = $DhcpFilesPath + ErrorAction = $SCT + } + + $DhcpBackupDatabasePathValue = (Get-ItemProperty @paramGetItemProperty | Select-Object -ExpandProperty 'BackupDatabasePath') + + if ($DhcpBackupDatabasePathValue) + { + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.mdb') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.pat') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.chk') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.edb') + $ExcludePathList += ($DhcpBackupDatabasePathValue + '\new\*.log') + } + } + else + { + Write-Verbose -Message 'No DHCP Server Directory found' + } + #endregion DhcpExclusions + + #region DnsExclusions + $DnsServerDir = "$env:windir\System32\dns" + + $paramTestPath = @{ + Path = $DnsServerDir + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $ExcludePathList += ($DnsServerDir + '\*.log') + $ExcludePathList += ($DnsServerDir + '\*.dns') + $ExcludePathList += ($DnsServerDir + '\BOOT') + + $DnsBackupServerDir = ($DnsServerDir + '\backup') + + $paramTestPath = @{ + Path = $DnsBackupServerDir + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $ExcludePathList += ($DnsBackupServerDir + '\*.log') + $ExcludePathList += ($DnsBackupServerDir + '\*.dns') + $ExcludePathList += ($DnsBackupServerDir + '\BOOT') + } + } + else + { + Write-Verbose -Message 'No DNS Server Directory found' + } + #endregion DnsExclusions + + #region WinsExclusions + $WinsServerDir = "$env:windir\System32\Wins" + + $paramTestPath = @{ + Path = $WinsServerDir + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + Write-Warning -Message 'WINS is still installed on this system!' -WarningAction Continue + + $ExcludePathList += ($WinsServerDir + '\*.chk') + $ExcludePathList += ($WinsServerDir + '\*.log') + $ExcludePathList += ($WinsServerDir + '\*.mdb') + } + else + { + Write-Verbose -Message 'No WINS Server Directory found' + } + #endregion WinsExclusions +} + +process +{ + if ($pscmdlet.ShouldProcess($ExcludePathList, 'Exclude from Microsoft Defender Scanning')) + { + # Loop over the list we created + foreach ($ExcludePath in $ExcludePathList) + { + try + { + # Splat the parameters for Add-MpPreference + $SplatAddMpPreference = @{ + ExclusionPath = $ExcludePath + Force = $true + ErrorAction = 'Stop' + WarningAction = 'Continue' + } + $null = (Add-MpPreference @SplatAddMpPreference) + } + catch + { + #region ErrorHandler + # get error record + [Management.Automation.ErrorRecord]$e = $_ + + # retrieve information about runtime error + $info = @{ + Exception = $e.Exception.Message + Reason = $e.CategoryInfo.Reason + Target = $e.CategoryInfo.TargetName + Script = $e.InvocationInfo.ScriptName + Line = $e.InvocationInfo.ScriptLineNumber + Column = $e.InvocationInfo.OffsetInLine + } + + # Error Stack + $info | Out-String | Write-Verbose + + # Just display the info on continue with the rest of the list + Write-Warning -Message ($info.Exception) -ErrorAction Continue -WarningAction Continue + + # Cleanup + $info = $null + $e = $null + #endregion ErrorHandler + } + } + } + + if ($pscmdlet.ShouldProcess($ExcludePathList, 'Tweak Controlled Folder AccessAllowed Applications')) + { + $paramGetMpPreference = @{ + ErrorAction = $SCT + } + $CurrentAllowedApplications = ((Get-MpPreference @paramGetMpPreference).ControlledFolderAccessAllowedApplications) + + # Prevent issues with missing allowed applications + if (-not ($CurrentAllowedApplications)) + { + # New installations might not have allowed applications, let us create an empty object + $CurrentAllowedApplications = @() + } + + $AllowedApplications = @( + 'C:\Program Files (x86)\KeePass Password Safe 2\KeePass.exe' + 'C:\Program Files\Intel\Intel(R) Rapid Storage Technology\IAStorDataMgrSvc.exe' + 'C:\ProgramData\chocolatey\lib\vlc\tools\vlc-*-win64_x64.exe' + 'C:\swsetup\SP*\HPImageAssistant.dll' + 'C:\Users\*\AppData\Local\Programs\Mark Text\Mark Text.exe' + 'C:\Users\*\AppData\Local\Temp\chocolatey\is-*.tmp\WinSCP-*-Setup.tmp' + 'C:\Windows\explorer.exe' + 'C:\Windows\System32\svchost.exe' + 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell_ise.exe' + ) + + $AllowedApplications | ForEach-Object -Process { + if (-not ($CurrentAllowedApplications.Contains($_))) + { + # Not the fasted way, but this will work just fine + $CurrentAllowedApplications += $_ + } + } + + try + { + # Apply the new (merged) allowed application list to the Defender Controlled Folder Access Allowed feature + $paramAddMpPreference = @{ + ControlledFolderAccessAllowedApplications = $CurrentAllowedApplications + Force = $true + ErrorAction = 'Stop' + } + $null = (Add-MpPreference @paramAddMpPreference) + } + catch + { + Write-Warning -Message 'Unable to modify the allow list...' + } + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# +DISCLAIMER: +- Use at your own risk, etc. +- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind +- This is a third-party Software +- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way +- The Software is not supported by Microsoft Corp (MSFT) +- By using the Software, you agree to the License, Terms, and any Conditions declared and described above +- If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/RemoteDesktop.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/RemoteDesktop.ps1 new file mode 100644 index 0000000..0d04a93 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/RemoteDesktop.ps1 @@ -0,0 +1,15 @@ +#requires -Version 1.0 + +if (-not ($ComputerName)) +{ + $ComputerName = $Env:COMPUTERNAME +} +$paramGetWmiObject = @{ + Class = 'Win32_TSGeneralSetting' + Namespace = 'root\cimv2\terminalservices' + ComputerName = $ComputerName + Filter = "TerminalName='RDP-tcp'" +} +$null = ((Get-WmiObject @paramGetWmiObject).SetUserAuthenticationRequired(0)) + +& "$env:windir\system32\net.exe" localgroup 'Remote Desktop Users' /add 'AzureAD\joerg@hochwald.net' diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Remove-AllPublicDesktopLinks.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Remove-AllPublicDesktopLinks.ps1 new file mode 100644 index 0000000..b074186 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Remove-AllPublicDesktopLinks.ps1 @@ -0,0 +1,96 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Removes all public Desktop Links + + .DESCRIPTION + Removes all public Desktop Links + + .NOTES + Still beta! + + Version 1.0.2 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Removes all public Desktop Links' + + #region GlobalDefaults + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + # Wait a moment to make the command above work (Otherwise the delete might get blocked!!!) + Start-Sleep -Seconds 5 + + $paramGetChildItem = @{ + Path = ($env:PUBLIC + '\Desktop\') + Filter = '*.lnk' + WarningAction = $SCT + ErrorAction = $SCT + } + + $paramRemoveItem = @{ + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + #endregion GlobalDefaults +} + +process +{ + if ($pscmdlet.ShouldProcess('All public Desktop Links', 'Remove')) + { + $null = (Get-ChildItem @paramGetChildItem | Select-Object -ExpandProperty FullName | Remove-Item @paramRemoveItem) + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# +DISCLAIMER: +- Use at your own risk, etc. +- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind +- This is a third-party Software +- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way +- The Software is not supported by Microsoft Corp (MSFT) +- By using the Software, you agree to the License, Terms, and any Conditions declared and described above +- If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Remove-GuestUserAccounts.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Remove-GuestUserAccounts.ps1 new file mode 100644 index 0000000..276d52b --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Remove-GuestUserAccounts.ps1 @@ -0,0 +1,128 @@ +#requires -Version 3.0 -Modules CimCmdlets, Microsoft.PowerShell.LocalAccounts -RunAsAdministrator + +<# + .SYNOPSIS + Remove given user and the matching profile + + .DESCRIPTION + Remove given user and the matching profile. + Created to remove all inactive guest users on a shared device + + .PARAMETER User + You can specify the Username or use wildcards + + .EXAMPLE + PS C:\> .\Remove-GuestUserAccounts.ps1 -User 'JohnDoe' + + Remove the user named 'JohnDoe', it also removes the Profile of the User. + + .EXAMPLE + PS C:\> .\Remove-GuestUserAccounts.ps1 -User 'enguest*' + + Remove all users that starts with 'enguest', it also removes all Profiles of these Users. + + .NOTES + Created to cleanup a shared device in aa conference room. + We run this script every day to save some diskspace and to delete all unneeded accounts. + All guest accounts on this system are one time users, so they are disabled after each use anyway. + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [ValidateNotNullOrEmpty()] + [Alias('UserAlias')] + [string] + $User = 'shpctac*' +) + +begin +{ + # Defaults + $SCT = 'SilentlyContinue' + + # Cleanup + $ExpiredGuests = $null +} + +process +{ + if ($pscmdlet.ShouldProcess($User, 'Delete')) + { + # Get all matching users + $paramGetLocalUser = @{ + Name = $User + ErrorAction = $SCT + WarningAction = $SCT + } + $ExpiredGuests = (Get-LocalUser @paramGetLocalUser | Where-Object -FilterScript { + $_.Enabled -eq $false + }) + + # Delete matching users, if we have some + if ($ExpiredGuests) + { + # Remove the User Account + $ExpiredGuests | ForEach-Object -Process { + $paramRemoveLocalUser = @{ + Name = ($_.Name) + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-LocalUser @paramRemoveLocalUser) + } + + # Remove the Profile + $ExpiredGuests | ForEach-Object -Process { + $paramGetCimInstance = @{ + ClassName = 'Win32_UserProfile' + ErrorAction = $SCT + WarningAction = $SCT + } + $paramRemoveCimInstance = @{ + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Get-CimInstance @paramGetCimInstance | Where-Object -FilterScript { + $_.LocalPath.split('\') -eq $_.Name + } | Remove-CimInstance @paramRemoveCimInstance) + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-AllowPingAndRemoteDesktop.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-AllowPingAndRemoteDesktop.ps1 new file mode 100644 index 0000000..7d08fb0 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-AllowPingAndRemoteDesktop.ps1 @@ -0,0 +1,171 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# +.SYNOPSIS +Enable inbound ICMP (Ping) and Remote Desktop (RDP) + +.DESCRIPTION +Enable inbound ICMP (Ping) and Remote Desktop (RDP). +Ping will be enabled for IPv4 and IPv6. + +.PARAMETER RDPGroup +Enable the complete RDP Groups in the Windows Firewall? +This will enable more then just the basic requirements, use with care!!! + +.EXAMPLE +PS C:\> .\Set-AllowPingAndRemoteDesktop.ps1 + +Enable inbound ICMP (Ping) and Remote Desktop (RDP) + +.EXAMPLE +PS C:\> .\Set-AllowPingAndRemoteDesktop.ps1 -verbose + +Enable inbound ICMP (Ping) and Remote Desktop (RDP) - verbose run + +.EXAMPLE +PS C:\> .\Set-AllowPingAndRemoteDesktop.ps1 -WhatIf + +Enable inbound ICMP (Ping) and Remote Desktop (RDP) - Dry run + +.NOTES +Helper script I use to bootstrap servers +Run this elevated!!! + +Version 1.0.4 + +.LINK +http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Medium', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline)] + [switch] + $RDPGroup +) + +begin +{ + Write-Output -InputObject 'Enable inbound ICMP (Ping) and Remote Desktop (RDP)' + + $SCT = 'SilentlyContinue' + $CNT = 'Continue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + # Splat the Set-ItemProperty parameters + $paramSetItemProperty = @{ + Path = 'HKLM:\System\CurrentControlSet\Control\Terminal Server' + Name = 'fDenyTSConnections' + Value = 0 + ErrorAction = $CNT + } + + # Splat the Enable-NetFirewallRule parameters + $paramEnableNetFirewallRule = @{ + Confirm = $false + ErrorAction = $CNT + } +} + +process +{ + # Support WhatIf (SupportsShouldProcess) + if ($pscmdlet.ShouldProcess('Registry Terminal Server', 'Modify')) + { + # Tweak the Registry for Remote Desktop connections + $null = (Set-ItemProperty @paramSetItemProperty) + } + + # We avoid using $RDPGroup.IsPresent + if ($PSBoundParameters.ContainsKey('RDPGroup')) + { + if ($pscmdlet.ShouldProcess('Firewall Group for Remote Desktop', 'Enable')) + { + # Allow Remote Desktop (The Group) + $paramGetNetFirewallRule = @{ + DisplayGroup = 'Remote Desktop' + ErrorAction = $SCT + } + $null = (Get-NetFirewallRule @paramGetNetFirewallRule | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule) + } + } + else + { + if ($pscmdlet.ShouldProcess('Firewall Rules for Remote Desktop', 'Enable')) + { + # Alternative Approach: Enable the minimum, not the Group + $paramGetNetFirewallRule = @{ + Name = 'RemoteDesktop-UserMode-In-TCP' + ErrorAction = $SCT + } + $null = (Get-NetFirewallRule @paramGetNetFirewallRule | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule) + + $paramGetNetFirewallRule = @{ + DisplayName = 'Remote Desktop - User Mode (TCP-In)' + ErrorAction = $SCT + } + $null = (Get-NetFirewallRule @paramGetNetFirewallRule | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule) + } + } + + if ($pscmdlet.ShouldProcess('Ping', 'Enable')) + { + # Allow Ping for IPv4 and IPv6 + # NOTE: The wildcard (ICMPv?) will select both. Replace it with 4 or 6 to use just one of them + $paramGetNetFirewallRule = @{ + DisplayName = 'File and Printer Sharing (Echo Request - ICMPv?-In)' + ErrorAction = $SCT + } + $null = (Get-NetFirewallRule @paramGetNetFirewallRule | Where-Object { + $_.Enabled -ne $true + } | Enable-NetFirewallRule @paramEnableNetFirewallRule) + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# +DISCLAIMER: +- Use at your own risk, etc. +- This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind +- This is a third-party Software +- The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way +- The Software is not supported by Microsoft Corp (MSFT) +- By using the Software, you agree to the License, Terms, and any Conditions declared and described above +- If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-DefaultStartMenu.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-DefaultStartMenu.ps1 new file mode 100644 index 0000000..d3da351 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-DefaultStartMenu.ps1 @@ -0,0 +1,221 @@ +#requires -Version 2.0 -RunAsAdministrator + +<# + .SYNOPSIS + Configure the Windows 10 Start Menu + + .DESCRIPTION + Configure the Windows 10 Start Menu + + .NOTES + Version 1.0.3 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Configure the Windows 10 Start Menu' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + $StartMenuContent = @' + + + + + + + + + + + + + + + + + + + + + + + + + + + +'@ + + $StartMenuFile = "$env:windir\StartMenuLayout.xml" +} + +process +{ + # Stop Search - Gain performance + $null = (Get-Service -Name 'WSearch' -ErrorAction $SCT | Where-Object -FilterScript { + $_.Status -eq 'Running' + } | Stop-Service -Force -Confirm:$false -ErrorAction $SCT) + + # Delete layout file if it already exists + $paramTestPath = @{ + Path = $StartMenuFile + ErrorAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $StartMenuFile + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + # Creates the blank layout file + $paramOutFile = @{ + FilePath = $StartMenuFile + Encoding = 'ASCII' + Force = $true + ErrorAction = $SCT + } + $null = ($StartMenuContent | Out-File @paramOutFile) + + $RegistryAliases = @('HKLM', 'HKCU') + + # Assign the start layout and force it to apply with "LockedStartLayout" at both the machine and user level + foreach ($RegistryAlias in $RegistryAliases) + { + $RegistryBasePath = ($RegistryAlias + ':\SOFTWARE\Policies\Microsoft\Windows') + $RegistryKeyPath = ($RegistryBasePath + '\Explorer') + + $paramTestPath = @{ + Path = $RegistryKeyPath + ErrorAction = $SCT + } + if (-not (Test-Path @paramTestPath)) + { + $paramNewItem = @{ + Path = $RegistryBasePath + Name = 'Explorer' + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $paramSetItemProperty = @{ + Path = $RegistryKeyPath + Name = 'LockedStartLayout' + Value = 1 + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + $paramSetItemProperty = @{ + Path = $RegistryKeyPath + Name = 'StartLayoutFile' + Value = $StartMenuFile + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + + # Restart Explorer, open the start menu (necessary to load the new layout) + $null = (Stop-Process -Name explorer) + + # Give it a few seconds to process + Start-Sleep -Seconds 5 + + $paramNewObject = @{ + ComObject = 'wscript.shell' + } + $WScriptShell = (New-Object @paramNewObject) + $WScriptShell.SendKeys('^{ESCAPE}') + + # Give it a few seconds to process + Start-Sleep -Seconds 5 + + # Enable the ability to pin items again by disabling "LockedStartLayout" + foreach ($RegistryAlias in $RegistryAliases) + { + $RegistryBasePath = $RegistryAlias + ':\SOFTWARE\Policies\Microsoft\Windows' + $RegistryKeyPath = $RegistryBasePath + '\Explorer' + $paramSetItemProperty = @{ + Path = $RegistryKeyPath + Name = 'LockedStartLayout' + Value = 0 + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Set-ItemProperty @paramSetItemProperty) + } + + # Restart Explorer and delete the layout file + Stop-Process -Name explorer + + # Uncomment the next line to make clean start menu default for all new users + # Import-StartLayout -LayoutPath $layoutFile -MountPath $env:SystemDrive\ + $paramRemoveItem = @{ + Path = $StartMenuFile + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-PowerPlanToAuto.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-PowerPlanToAuto.ps1 new file mode 100644 index 0000000..6fcf31a --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-PowerPlanToAuto.ps1 @@ -0,0 +1,192 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Set the Windows Power Plan based on the computer type + + .DESCRIPTION + Set the Windows Power Plan based on the computer type, it also set the Hibernation + With Version 1.1 we introduced Support for the Parallels Power Schema + + .EXAMPLE + PS C:\> .\Set-PowerPlanToAuto.ps1 + + .NOTES + + Version 1.1.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Set the Windows Power Plan to Auto' + + #region + $SCT = 'SilentlyContinue' + #endregion + + #region + $paramGetWmiObject = @{ + Namespace = 'root\cimv2\power' + Class = 'Win32_PowerPlan' + ErrorAction = $SCT + } + #endregion + + #region + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + #endregion + + #region + function Get-ActiveWindowsPowerPlan + { + <# + .SYNOPSIS + Get the active Windows Power Plan + + .DESCRIPTION + Get the active Windows Power Plan + + .PARAMETER AllPowerPlans + All Power Plans that Windows knows about + + .EXAMPLE + PS C:\> Get-ActiveWindowsPowerPlan + + .NOTES + Internal Helper + #> + [CmdletBinding(ConfirmImpact = 'None')] + [OutputType([string])] + param + ( + [Parameter(Mandatory, + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0, + HelpMessage = 'Object with all Power Plans')] + [ValidateNotNullOrEmpty()] + [psobject] + $AllPowerPlans + ) + + begin + { + #region + $ActivePowerPlan = $null + #endregion + } + + process + { + #$AllPowerPlans = (Get-WmiObject @paramGetWmiObject | Select-Object -Property ElementName, InstanceID, IsActive) + $ActivePowerPlan = ($AllPowerPlans | Where-Object -FilterScript { + $_.IsActive -eq $true + } | Select-Object -ExpandProperty ElementName) + } + + end + { + $ActivePowerPlan + } + } + #endregion +} + +process +{ + # Get all Power Plans + $AllPowerPlans = (Get-WmiObject @paramGetWmiObject | Select-Object -Property ElementName, InstanceID, IsActive) + + # Get the active Power Plan + $ActivePowerPlan = (Get-ActiveWindowsPowerPlan -AllPowerPlans $AllPowerPlans -ErrorAction $SCT) + + Write-Verbose -Message ('Active Power Plan: {0}' -f $ActivePowerPlan) + + if ((($AllPowerPlans).ElementName) -ccontains 'Parallels') + { + # Looks like this system is a VM on Parallels + $RunOnParallels = ($AllPowerPlans | Where-Object { + $_.ElementName -ccontains 'Parallels' + } | Select-Object -ExpandProperty InstanceID) + + # Extract the ID of the Power Schema + $RunOnParallels = ([Regex]::Matches($RunOnParallels, '(?<={)(.*?)(?=})') | Select-Object -ExpandProperty Value) + + # Activate the Parallels Schema + $null = (& "$env:windir\system32\powercfg.exe" /SETACTIVE $RunOnParallels) + + # Disable Hybernation + $null = (& "$env:windir\system32\powercfg.exe" /HIBERNATE OFF) + } + elseif ((Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction $SCT).PCSystemType -eq 2) + { + # Balanced for laptop + $null = (& "$env:windir\system32\powercfg.exe" /SETACTIVE SCHEME_BALANCED) + + # Enable Hybernation + $null = (& "$env:windir\system32\powercfg.exe" /HIBERNATE ON) + } + else + { + # High performance for desktop + $null = (& "$env:windir\system32\powercfg.exe" /SETACTIVE SCHEME_MIN) + + # Disable Hybernation + $null = (& "$env:windir\system32\powercfg.exe" /HIBERNATE OFF) + } + + # Get all Power Plans + $AllPowerPlans = (Get-WmiObject @paramGetWmiObject | Select-Object -Property ElementName, InstanceID, IsActive) + + # Get the active Power Plan + $ActivePowerPlan = (Get-ActiveWindowsPowerPlan -AllPowerPlans $AllPowerPlans -ErrorAction $SCT) + + Write-Verbose -Message ('Active Power Plan: {0}' -f $ActivePowerPlan) +} + +end +{ + #region + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } + #endregion +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-PowerPlanToHighPerformance.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-PowerPlanToHighPerformance.ps1 new file mode 100644 index 0000000..ee90060 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-PowerPlanToHighPerformance.ps1 @@ -0,0 +1,138 @@ +#requires -Version 2.0 -RunAsAdministrator + +<# + .SYNOPSIS + Set the Windows Power Plan to High Performance + + .DESCRIPTION + Set the Windows Power Plan to High Performance, it also disables Hybernation and System Standby + + .EXAMPLE + PS C:\> .\Set-PowerPlanToHighPerformance.ps1 + + .NOTES + Works fine on Windows Server 2016 (Developed for server use) and Windows 10. + + Version 1.5.9 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low')] +param () + +begin +{ + Write-Output -InputObject 'Set the Windows Power Plan to High Performance' + + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } +} + +process +{ + # Stop Search - Gain performance + $null = (Get-Service -Name 'WSearch' -ErrorAction $SCT | Where-Object -FilterScript { + $_.Status -eq 'Running' + } | Stop-Service -Force -Confirm:$false -ErrorAction $SCT) + + #region + $null = (& "$env:windir\system32\powercfg.exe" /SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c) + #endregion + + #region Cleanup + $ActivePowerPlan = $null + $PowerPlanHighPowerState = $null + #endregion Cleanup + + #region InformationGathering + # Splat the parameters + $paramGetWmiObject = @{ + Namespace = 'root\cimv2\power' + Class = 'Win32_PowerPlan' + ErrorAction = $SCT + } + + # Gather the PowerPlan information + $ActivePowerPlan = (Get-WmiObject @paramGetWmiObject | Select-Object -Property ElementName, InstanceID, IsActive) + + # Filter the 'High Performance' plan info + $PowerPlanHighPowerState = $ActivePowerPlan | Where-Object -FilterScript { + $_.InstanceID -eq 'Microsoft:PowerPlan\{8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}' + } + #endregion InformationGathering + + #region CheckIfTheTweakIsNeeded + if ($PowerPlanHighPowerState.IsActive -ne $true) + { + $null = (& "$env:windir\system32\powercfg.exe" /SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c) + $null = (& "$env:windir\system32\powercfg.exe" /SETACTIVE 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c) + } + #endregion CheckIfTheTweakIsNeeded + + #region Cleanup + $PowerPlanHighPowerState = $null + #endregion Cleanup + + #region Retest + $PowerPlanHighPowerState = $ActivePowerPlan | Where-Object -FilterScript { + $_.InstanceID -eq 'Microsoft:PowerPlan\{8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c}' + } + + # Filter the 'High Performance' plan info + if ($PowerPlanHighPowerState.IsActive -ne $true) + { + Write-Warning -Message "Unable to set the PowerPlan to 'High Performance'" + } + #endregion Retest + + #region NoStandBy + $null = (& "$env:windir\system32\powercfg.exe" -change -standby-timeout-ac 0) + #endregion NoStandBy + + #region DisableHybernationSupport + $null = (& "$env:windir\system32\powercfg.exe" /HIBERNATE OFF) + $null = (& "$env:windir\system32\powercfg.exe" -change -hibernate-timeout-ac 0) + #endregion DisableHybernationSupport +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-QoSForMicrosoftTeams.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-QoSForMicrosoftTeams.ps1 new file mode 100644 index 0000000..7b585d9 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-QoSForMicrosoftTeams.ps1 @@ -0,0 +1,223 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Apply QoS Settings for Microsoft Teams + + .DESCRIPTION + Apply Network Quality of Service (QoS) settings for Microsoft Teams. + + .PARAMETER AppPathNameMatchCondition + Specifies the name by which an application is run, such as application.exe or %ProgramFiles%\application.exe application. + + .EXAMPLE + PS C:\> .\Set-QoSForMicrosoftTeams.ps1 + + .EXAMPLE + PS C:\> .\Set-QoSForMicrosoftTeamsRoom.ps1 -AppPathNameMatchCondition 'Teams.exe' + + .NOTES + Changelog: + 1.0.0: Initial Release (Adopted from Set-QoSForMicrosoftTeamsRoomDevices.ps1) + + Version 1.0.0 + + .LINK + Get-NetQosPolicy + + .LINK + New-NetQosPolicy + + .LINK + https://docs.microsoft.com/en-us/microsoftteams/qos-in-teams-clients + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param +( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName)] + [Alias('AppName')] + [string] + $AppPathNameMatchCondition = 'Teams.exe' +) + +begin +{ + Write-Output -InputObject 'Apply Network Quality of Service (QoS) settings for Microsoft Teams' + + #region Defaults + $CNT = 'Continue' + $STP = 'Stop' + $SCT = 'SilentlyContinue' + + [string]$AppSharingPolicy = 'Microsoft Teams AppSharing' + [string]$VideoPolicy = 'Microsoft Teams Video' + [string]$AudioPoliy = 'Microsoft Teams Audio' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } +} + +process +{ + if ($pscmdlet.ShouldProcess('QoS-Settings', 'Apply')) + { + #region Audio + $paramGetNetQosPolicy = @{ + Name = $AudioPoliy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50000 + IPSrcPortEndMatchCondition = 50019 + DSCPAction = 46 + IPProtocolMatchCondition = 'Both' + Name = $AudioPoliy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $AudioPoliy) + } + } + #endregion Audio + + #region Video + $paramGetNetQosPolicy = @{ + Name = $VideoPolicy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50020 + IPSrcPortEndMatchCondition = 50039 + DSCPAction = 34 + IPProtocolMatchCondition = 'Both' + Name = $VideoPolicy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $VideoPolicy) + } + } + #endregion Video + + #region AppSharing + $paramGetNetQosPolicy = @{ + Name = $AppSharingPolicy + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not (Get-NetQosPolicy @paramGetNetQosPolicy)) + { + try + { + # Splat the parameters + $paramNewNetQosPolicy = @{ + NetworkProfile = 'All' + IPSrcPortStartMatchCondition = 50040 + IPSrcPortEndMatchCondition = 50059 + DSCPAction = 28 + IPProtocolMatchCondition = 'Both' + Name = $AppSharingPolicy + Confirm = $false + WarningAction = $CNT + ErrorAction = $STP + } + + # Do we have an application name? + if ($AppPathNameMatchCondition) + { + $paramNewNetQosPolicy.Add('AppPathNameMatchCondition', $AppPathNameMatchCondition) + } + + $null = (New-NetQosPolicy @paramNewNetQosPolicy) + } + catch + { + Write-Warning -Message ('Unable to apply {0} QoS Poliy' -f $AppSharingPolicy) + } + } + #endregion AppSharing + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-StorageSense.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-StorageSense.ps1 new file mode 100644 index 0000000..3ac0575 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-StorageSense.ps1 @@ -0,0 +1,289 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Configure Storage Sense for Windows 10 + + .DESCRIPTION + Configure Storage Sense for Windows 10 + + .EXAMPLE + PS C:\> .\Set-StorageSense.ps1 + + .NOTES + Version 1.0.3 + + Use Set-StorageSense Version 1.0 from Jaap Brasser + + .LINK + https://github.com/jaapbrasser/SharedScripts/blob/master/Set-StorageSense/Set-StorageSense.ps1 +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + Write-Output -InputObject 'Configure Storage Sense for Windows 10' + + #region Defaults + $SCT = 'SilentlyContinue' + #endregion Defaults + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + function Set-StorageSense + { + <# + .SYNOPSIS + Configures the Storage Sense options in Windows 10 + + .DESCRIPTION + This function can configure Storage Sense options in Windows 10. It allows to enable/disable this feature + + .PARAMETER EnableStorageSense + Enables storage sense setting, automatically cleaning up space on your system + + .PARAMETER DisableStorageSense + Disables storage sense setting, not automatically cleaning up space on your system + + .PARAMETER RemoveAppFiles + Configures the 'Delete temporary files that my apps aren't using' to either true or false + + .PARAMETER ClearRecycleBin + Configures the 'Delete files that have been in the recycle bin for over 30 days' to either true or false + + .NOTES + Name: Set-StorageSense + Author: Jaap Brasser + DateCreated: 2017-01-26 + DateUpdated: 2017-01-26 + Version: 1.0.0 + Blog: http://www.jaapbrasser.com + + .LINK + http://www.jaapbrasser.com + + .EXAMPLE + Set-StorageSense -DisableStorageSense + + Description + ----------- + Disables Storage Sense on the system + + .EXAMPLE + Set-StorageSense -EnableStorageSense -RemoveAppFiles $true + + Description + ----------- + Enables Storage Sense on the system and sets the 'Delete temporary files that my apps aren't using' to enabled + + .EXAMPLE + Set-StorageSense -DisableStorageSense -RemoveAppFiles $true -ClearRecycleBin $true -Verbose + + Description + ----------- + Disables Storage Sense on the system and sets both the 'Delete temporary files that my apps aren't using' and the 'Delete files that have been in the recycle bin for over 30 days' to enabled + #> + [cmdletbinding(SupportsShouldProcess)] + param ( + [Parameter( + Mandatory, HelpMessage = 'Add help message for user', + ParameterSetName = 'StorageSense On' + )] + [switch] + $EnableStorageSense, + [Parameter( + Mandatory, HelpMessage = 'Add help message for user', + ParameterSetName = 'StorageSense Off' + )] + [switch] + $DisableStorageSense, + [Parameter( + ParameterSetName = 'StorageSense On' + )] + [Parameter( + ParameterSetName = 'StorageSense Off' + )] + [Parameter( + ParameterSetName = 'Configure StorageSense' + )] + [bool] + $RemoveAppFiles, + [Parameter( + ParameterSetName = 'StorageSense On' + )] + [Parameter( + ParameterSetName = 'StorageSense Off' + )] + [Parameter( + ParameterSetName = 'Configure StorageSense' + )] + [bool] + $ClearRecycleBin + ) + + begin + { + $RegPath = @{ + StorageSense = '01' + TemporaryApp = '04' + RecycleBin = '08' + } + $SetRegistrySplat = @{ + Path = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\StorageSense\Parameters\StoragePolicy\' + Name = $null + Value = $null + } + + function Set-RegistryValue + { + <# + .SYNOPSIS + Describe purpose of "Set-RegistryValue" in 1-2 sentences. + + .DESCRIPTION + Add a more complete description of what the function does. + + .PARAMETER Path + Describe parameter -Path. + + .PARAMETER Name + Describe parameter -Name. + + .PARAMETER Value + Describe parameter -Value. + + .EXAMPLE + Set-RegistryValue -Path Value -Name Value -Value Value + Describe what this call does + + .NOTES + Place additional notes here. + + .LINK + URLs to related sites + The first link is opened by Get-Help -Online Set-RegistryValue + + .INPUTS + List of input types that are accepted by this function. + + .OUTPUTS + List of output types produced by this function. + #> + [CmdletBinding()] + param ( + [string] + $Path, + [string] + $Name, + [string] + $Value + ) + + if (-not (Test-Path -Path $Path -ErrorAction SilentlyContinue)) + { + if ($PSCmdlet.ShouldProcess("$Path$Name : $Value", 'Creating registry key')) + { + $null = New-Item -Path $Path -Force -ErrorAction SilentlyContinue + } + } + + if ($PSCmdlet.ShouldProcess("$Path$Name : $Value", 'Updating registry value')) + { + $null = Set-ItemProperty @PSBoundParameters -Force -ErrorAction SilentlyContinue + } + } + } + + process + { + switch (1) + { + { + $PSCmdlet.ParameterSetName -eq 'StorageSense On' + } + { + $SetRegistrySplat.Name = $RegPath.StorageSense + $SetRegistrySplat.Value = 1 + Set-RegistryValue @SetRegistrySplat + } + { + $PSCmdlet.ParameterSetName -eq 'StorageSense Off' + } + { + $SetRegistrySplat.Name = $RegPath.StorageSense + $SetRegistrySplat.Value = 0 + Set-RegistryValue @SetRegistrySplat + } + { + $PSBoundParameters.Keys -contains 'RemoveAppFiles' + } + { + $SetRegistrySplat.Name = $RegPath.TemporaryApp + $SetRegistrySplat.Value = [int]$RemoveAppFiles + Set-RegistryValue @SetRegistrySplat + } + { + $PSBoundParameters.Keys -contains 'ClearRecycleBin' + } + { + $SetRegistrySplat.Name = $RegPath.RecycleBin + $SetRegistrySplat.Value = [int]$ClearRecycleBin + Set-RegistryValue @SetRegistrySplat + } + } + } + } +} + +process +{ + $paramSetStorageSense = @{ + EnableStorageSense = $true + RemoveAppFiles = $true + ClearRecycleBin = $true + Verbose = $true + ErrorAction = $SCT + } + $null = (Set-StorageSense @paramSetStorageSense) +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-SystemStartMenuDefault.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-SystemStartMenuDefault.ps1 new file mode 100644 index 0000000..a720fe6 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-SystemStartMenuDefault.ps1 @@ -0,0 +1,841 @@ +#requires -Version 1.0 -RunAsAdministrator + +<# + .SYNOPSIS + Setup the default enaTec Start Menu for the System + + .DESCRIPTION + Setup the default enaTec Start Menu for the System + + .EXAMPLE + PS C:\> .\Set-SystemStartMenuDefault.ps1 + + .NOTES + Minor Helper + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + Write-Output -InputObject 'Setup the default enaTec Start Menu for the System' + + #region Defaults + $SCT = 'SilentlyContinue' + $BasePath = "$env:ProgramData\Microsoft\Windows\Start Menu\Programs" + #endregion Defaults +} + +process +{ + #region 7Zip + $FolderName = '\7-Zip' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\7-Zip File Manager.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion 7Zip + + #region Barco + $FolderName = '\Barco' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\ClickShare.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $ClickShareLauncher = ($FolderPath + '\ClickShare Launcher\ClickShare Launcher.lnk') + + $paramTestPath = @{ + Path = $ClickShareLauncher + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = $ClickShareLauncher + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + } + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion Barco + + #region CMake + $FolderName = '\CMake' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\CMake (cmake-gui).lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion CMake + + #region Cyberduck + $FolderName = '\Cyberduck' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\Cyberduck.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion Cyberduck + + #region Git + $FolderName = '\Git' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\Git GUI.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion Git + + #region HPHelpAndSupport + $FolderName = '\HP Help and Support' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\HP Support Assistant.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion HPHelpAndSupport + + #region KeePassXC + $FolderName = '\KeePassXC' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\KeePassXC.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion KeePassXC + + #region LockHunter + $FolderName = '\LockHunter' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\LockHunter.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion LockHunter + + #region MicrosoftIntuneManagementExtension + $FolderName = '\Microsoft Intune Management Extension' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion MicrosoftIntuneManagementExtension + + #region MicrosoftSilverlight + $FolderName = '\Microsoft Silverlight' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion MicrosoftSilverlight + + #region Python + $FolderName = '\Python 3.9' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion Python + + #region Node.js + $FolderName = '\Node.js' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\Node.js.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion Node.js + + #region VideoLAN + $FolderName = '\VideoLAN' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\VLC media player.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion VideoLAN + + #region WinMerge + $FolderName = '\WinMerge' + $FolderPath = ($BasePath + $FolderName) + + $paramTestPath = @{ + Path = $FolderPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($FolderPath + '\WinMerge.lnk') + Destination = $BasePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + + $paramRemoveItem = @{ + Path = $FolderPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion WinMerge + + #region Yubico + $Yubico = '\Yubico' + $YubicoPath = ($BasePath + $Yubico) + $YubicoAuthenticator = '\Yubico Authenticator' + $YubicoAuthenticatorPath = ($BasePath + $YubicoAuthenticator) + + $paramTestYubicoPath = @{ + Path = $YubicoPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + $paramTestYubicoAuthenticatorPath = @{ + Path = $YubicoAuthenticatorPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if ((Test-Path @paramTestYubicoPath ) -and (Test-Path @paramTestYubicoAuthenticatorPath)) + { + # Move the Yubico Authenticator to the Yubico directory + $paramMoveItem = @{ + Path = $YubicoAuthenticatorPath + Destination = $YubicoPath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + + # Remove some links + $paramRemoveItem = @{ + Path = ($YubicoPath + '\Yubikey Manager\Uninstall YubiKey Manager.lnk') + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + + $paramRemoveItem = @{ + Path = ($YubicoPath + '\YubiKey Personalization Tool\Uninstall.lnk') + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + + $paramRemoveItem = @{ + Path = ($YubicoPath + '\YubiKey Personalization Tool\Yubico Web page.url') + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + + $paramRemoveItem = @{ + Path = ($YubicoPath + '\YubiKey PIV Manager\Uninstall YubiKey PIV Manager.lnk') + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion Yubico + + #region Structure + #region Dev + $RegionName = 'Dev' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $MoveItems = @( + 'CMake (cmake-gui)' + 'Git GUI' + 'Node.js' + 'WinMerge' + ) + + foreach ($MoveItem in $MoveItems) + { + $MoveItemPath = ($BasePath + '\' + $MoveItem + '.lnk') + + $paramTestPath = @{ + Path = $MoveItemPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MoveItemPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + } + #endregion Dev + + #region Tools + $RegionName = 'Tools' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $MoveItems = @( + '7-Zip File Manager' + 'Chocolatey Cleaner' + 'Chocolatey GUI' + 'ClickShare Launcher' + 'ClickShare' + 'Cyberduck' + 'KeePass 2' + 'KeePassXC' + 'LockHunter' + 'Make Me Admin' + 'paint.net' + 'PowerToys (Preview)' + 'VLC media player' + 'WinSCP' + ) + + foreach ($MoveItem in $MoveItems) + { + $MoveItemPath = ($BasePath + '\' + $MoveItem + '.lnk') + + $paramTestPath = @{ + Path = $MoveItemPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MoveItemPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + } + #endregion Tools + + #region Browser + $RegionName = 'Browser' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $MoveItems = @( + 'Chromium' + 'Firefox' + 'Google Chrome' + 'Microsoft Edge Beta' + 'Microsoft Edge' + ) + + foreach ($MoveItem in $MoveItems) + { + $MoveItemPath = ($BasePath + '\' + $MoveItem + '.lnk') + + $paramTestPath = @{ + Path = $MoveItemPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MoveItemPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + } + #endregion Browser + + #region Office + $RegionName = 'Microsoft Office' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + $MoveItems = @( + 'Excel' + 'OneNote 2016' + 'Outlook' + 'PowerPoint' + 'Project' + 'Visio' + 'Word' + ) + + foreach ($MoveItem in $MoveItems) + { + $MoveItemPath = ($BasePath + '\' + $MoveItem + '.lnk') + + $paramTestPath = @{ + Path = $MoveItemPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MoveItemPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + } + #endregion Office + #endregion Structure +} + +end +{ + exit (0) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-UserStartMenuDefault.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-UserStartMenuDefault.ps1 new file mode 100644 index 0000000..9af0ea2 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Set-UserStartMenuDefault.ps1 @@ -0,0 +1,536 @@ +#requires -Version 1.0 + +<# + .SYNOPSIS + Setup the default enaTec Start Menu for the User + + .DESCRIPTION + Setup the default enaTec Start Menu for the User + + .EXAMPLE + PS C:\> .\Set-UserStartMenuDefault.ps1 + + .NOTES + Minor Helper + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'None')] +param () + +begin +{ + Write-Output -InputObject 'Setup the default enaTec Start Menu for the User' + + #region Defaults + $SCT = 'SilentlyContinue' + $BasePath = ("$env:HOMEDRIVE\Users\" + $env:USERNAME + '\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\') + #endregion Defaults +} + +process +{ + #region Structure + #region Dev + $RegionName = 'Dev' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + #region Fiddler + $FiddlerPath = ($BasePath + '\Fiddler 4.lnk') + + $paramTestPath = @{ + Path = $FiddlerPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $FiddlerPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + + $FiddlerScriptEditorPath = ($BasePath + '\Fiddler ScriptEditor.lnk') + + $paramTestPath = @{ + Path = $FiddlerScriptEditorPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $FiddlerScriptEditorPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + + $null = (Move-Item @paramMoveItem) + } + #endregion Fiddler + + #region GitHubInc + $GitHubIncPath = ($BasePath + '\GitHub, Inc\GitHub Desktop.lnk') + + $paramTestPath = @{ + Path = $GitHubIncPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $GitHubIncPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + + $GitHubIncPath = ($BasePath + '\GitHub, Inc\') + + $paramTestPath = @{ + Path = $GitHubIncPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $GitHubIncPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion GitHubInc + + #region Postman + $PostmanPath = ($BasePath + '\Postman\Postman.lnk') + + $paramTestPath = @{ + Path = $PostmanPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $PostmanPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + + $PostmanPath = ($BasePath + '\Postman') + + $paramTestPath = @{ + Path = $PostmanPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $PostmanPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion Postman + + #region MarkPad + $MarkPadPath = ($BasePath + '\MarkPad\MarkPad.lnk') + + $paramTestPath = @{ + Path = $MarkPadPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MarkPadPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + + $MarkPadPath = ($BasePath + '\MarkPad') + + $paramTestPath = @{ + Path = $MarkPadPath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $MarkPadPath + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion MarkPad + #endregion Dev + + #region Tools + $RegionName = 'Tools' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + #region AutoDarkMode + $AutoDarkModePath = ($BasePath + '\Auto Dark Mode.lnk') + + $paramTestPath = @{ + Path = $AutoDarkModePath + ErrorAction = $SCT + WarningAction = $SCT + } + + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $AutoDarkModePath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + #endregion AutoDarkMode + + #region MarkText + $MarkTextPath = ($BasePath + '\Mark Text.lnk') + + $paramTestPath = @{ + Path = $MarkTextPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MarkTextPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + #endregion MarkText + + #region Graphviz + $paramGetItem = @{ + Path = ($BasePath + '\Graphviz*') + Force = $true + ErrorAction = $SCT + WarningAction = $SCT + } + $GraphvizBasePath = (Get-Item @paramGetItem | Select-Object -ExpandProperty Name) + + if ($GraphvizBasePath) + { + $paramTestPath = @{ + Path = ($BasePath + '\' + $GraphvizBasePath + '\gvedit.exe.lnk') + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramCopyItem = @{ + Path = ($BasePath + '\' + $GraphvizBasePath + '\gvedit.exe.lnk') + Destination = ($RegionNamePath + '\Graphviz.lnk') + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Copy-Item @paramCopyItem) + } + + $paramRemoveItem = @{ + Path = ($BasePath + '\' + $GraphvizBasePath) + Recurse = $true + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + + $MarkTextPath = ($BasePath + '\Mark Text.lnk') + + $paramTestPath = @{ + Path = $MarkTextPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MarkTextPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + #endregion Graphviz + #endregion Tools + + #region Browser + $RegionName = 'Browser' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + #region Brave + $BravePath = ($BasePath + '\Brave.lnk') + + $paramTestPath = @{ + Path = $BravePath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $BravePath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + #endregion Brave + #endregion Browser + + #region Office + $RegionName = 'Office' + $RegionNamePath = ($BasePath + '\' + $RegionName) + + $paramTestPath = @{ + Path = $RegionNamePath + PathType = 'Container' + ErrorAction = $SCT + WarningAction = $SCT + } + if (-not ((Test-Path @paramTestPath))) + { + $paramNewItem = @{ + Path = ($BasePath) + Name = $RegionName + ItemType = 'Directory' + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (New-Item @paramNewItem) + } + + #region MicrosoftTeams + $MicrosoftTeamsPath = ($BasePath + '\Microsoft Teams.lnk') + + $paramTestPath = @{ + Path = $MicrosoftTeamsPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $MicrosoftTeamsPath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + #endregion MicrosoftTeams + + #region OneDrive + $OneDrivePath = ($BasePath + '\OneDrive.lnk') + + $paramTestPath = @{ + Path = $OneDrivePath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramMoveItem = @{ + Path = $OneDrivePath + Destination = $RegionNamePath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Move-Item @paramMoveItem) + } + #endregion OneDrive + #endregion Office + #endregion Structure + + #region UninstallPIVManager + $UninstallPIVManagerPath = ($BasePath + '\Yubico\Yubikey PIV Manager\Uninstall PIV Manager.lnk') + + $paramTestPath = @{ + Path = $UninstallPIVManagerPath + ErrorAction = $SCT + WarningAction = $SCT + } + if (Test-Path @paramTestPath) + { + $paramRemoveItem = @{ + Path = $UninstallPIVManagerPath + Force = $true + Confirm = $false + ErrorAction = $SCT + WarningAction = $SCT + } + $null = (Remove-Item @paramRemoveItem) + } + #endregion UninstallPIVManager +} + +end +{ + exit (0) +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Update-AllMicrosoftStoreApps.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Update-AllMicrosoftStoreApps.ps1 new file mode 100644 index 0000000..8b66ba3 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Update-AllMicrosoftStoreApps.ps1 @@ -0,0 +1,107 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Update all Microsoft Store Apps + + .DESCRIPTION + Update all Microsoft Store Apps + + .NOTES + There is a scheduled task that does this job, but we would like to enforce it! + New version that use CIM instead of WMI + + Version 1.0.0 + + .LINK + http://enatec.io +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Update all Microsoft Store Apps' + + #region GlobalDefaults + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + # Wait a moment to make the command above work (Otherwise the delete might get blocked!!!) + Start-Sleep -Seconds 2 + + $paramGetCimInstance = @{ + Namespace = 'Root\cimv2\mdm\dmmap' + ClassName = 'MDM_EnterpriseModernAppManagement_AppManagement01' + ErrorAction = $SCT + } + + $paramInvokeCimMethod = @{ + MethodName = 'UpdateScanMethod' + ErrorAction = $SCT + } + #endregion GlobalDefaults +} + +process +{ + if ($pscmdlet.ShouldProcess('All Microsoft Store Apps', 'Update')) + { + # Stop Search - Gain performance + $paramGetService = @{ + Name = 'WSearch' + ErrorAction = $SCT + } + $paramStopService = @{ + Force = $true + Confirm = $false + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + $null = (Get-CimInstance @paramGetCimInstance | Invoke-CimMethod @paramInvokeCimMethod) + } +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Update-PowerShellModulesHelp.ps1 b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Update-PowerShellModulesHelp.ps1 new file mode 100644 index 0000000..3baa946 --- /dev/null +++ b/Powershell/PowerShell-collection/Windows10-Bootstrapper/sources/$OEM$/$1/scripts/PowerShell/Update-PowerShellModulesHelp.ps1 @@ -0,0 +1,126 @@ +#requires -Version 3.0 -RunAsAdministrator + +<# + .SYNOPSIS + Update all help files for all installed PowerShell Modules + + .DESCRIPTION + Update all help files for all installed PowerShell Modules + + .LINK + http://enatec.io + + .NOTES + Version 1.0.2 +#> +[CmdletBinding(ConfirmImpact = 'Low', + SupportsShouldProcess)] +param () + +begin +{ + Write-Output -InputObject 'Update all help files for all installed PowerShell Modules' + + #region GlobalDefaults + $SCT = 'SilentlyContinue' + + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Disabled -Force -ErrorAction $SCT) + } + + # Wait a moment to make the command above work (Otherwise the delete might get blocked!!!) + Start-Sleep -Seconds 2 + #endregion GlobalDefaults +} + +process +{ + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + + $paramGetService = @{ + Name = 'WSearch' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Update the Module Information + $paramGetModule = @{ + ListAvailable = $true + Refresh = $true + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Module @paramGetModule) + + # Stop Search - Gain performance + $paramStopService = @{ + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $paramGetService = @{ + Name = 'WSearch' + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Get-Service @paramGetService | Where-Object { + $_.Status -eq 'Running' + } | Stop-Service @paramStopService) + + # Update the Help + $paramUpdateHelp = @{ + Force = $true + Confirm = $false + WarningAction = $SCT + ErrorAction = $SCT + } + $null = (Update-Help @paramUpdateHelp) +} + +end +{ + if (Get-Command -Name 'Set-MpPreference' -ErrorAction $SCT) + { + $null = (Set-MpPreference -EnableControlledFolderAccess Enabled -Force -ErrorAction $SCT) + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the Terms, and any Conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/bdc.MtrTooling/readme.md b/Powershell/PowerShell-collection/bdc.MtrTooling/readme.md new file mode 100644 index 0000000..e346073 --- /dev/null +++ b/Powershell/PowerShell-collection/bdc.MtrTooling/readme.md @@ -0,0 +1,3 @@ +# bdc.MtrTooling + +New location: [https://github.com/jhochwald/bdc.MtrTooling](https://github.com/jhochwald/bdc.MtrTooling) diff --git a/Powershell/PowerShell-collection/bdcBusylight/LICENSE b/Powershell/PowerShell-collection/bdcBusylight/LICENSE new file mode 100644 index 0000000..2be7693 --- /dev/null +++ b/Powershell/PowerShell-collection/bdcBusylight/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2021, enabling Technology +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/Powershell/PowerShell-collection/bdcBusylight/bdcBusylight.ps1 b/Powershell/PowerShell-collection/bdcBusylight/bdcBusylight.ps1 new file mode 100644 index 0000000..39a9dff --- /dev/null +++ b/Powershell/PowerShell-collection/bdcBusylight/bdcBusylight.ps1 @@ -0,0 +1,273 @@ +function Set-bdcBusylightColor +{ + <# + .SYNOPSIS + Set the color of a connected Kuando Busylight device + + .DESCRIPTION + Set the color of a connected Kuando Busylight device + + .PARAMETER Color + Only the following colors are supported: + - blue + - cyan + - green + - magenta + - orange + - red + - white + - yellow + - off + + Where off is not a color, as it should tell, it will turn the Busylight off! + The default is off - If you invoke the function without any parameter, it will be turned off. + + .EXAMPLE + PS C:\> Set-bdcBusylightColor + + Turn the Busylight off + + .EXAMPLE + PS C:\> Set-bdcBusylightColor -Color green + + Set the Busylight color to green + + .LINK + https://docs.microsoft.com/en-us/graph/api/resources/presence?view=graph-rest-beta + + .LINK + https://docs.microsoft.com/en-us/graph/api/presence-get?view=graph-rest-beta + + .LINK + https://www.plenom.com/support/develop/ + + .NOTES + You will need the BusylightSDK.DLL, as the PowerShell scripts communicates with the device by calling functions in the DLL. + You can get it from the SDK, at https://www.plenom.com/support/develop/. + #> + + [CmdletBinding(ConfirmImpact = 'None', + SupportsShouldProcess)] + param + ( + [Parameter(ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [ValidateSet('blue', 'cyan', 'green', 'magenta', 'orange', 'red', 'white', 'yellow', 'off', IgnoreCase = $true)] + [Alias('BusylightColor')] + [string] + $Color = 'off ' + ) + + begin + { + # Cleanup + $MyBusyLight = $null + + # This is the path to the BusyLight SDK DLL. Correct path as needed. + $BusylightSDKDll = [IO.Path]::Combine((Split-Path -Path $script:MyInvocation.MyCommand.Path -Parent), 'BusylightSDK.dll') + + if (-not (Test-Path -Path $BusylightSDKDll)) + { + # Try a fallback + Write-Warning "Whhops, $BusylightSDKDll was NOT found, we try a fallback method." + $BusylightSDKDll = [IO.Path]::Combine('.\', 'BusylightSDK.dll') + } + + $null = (Add-Type -Path $BusylightSDKDll -ErrorAction Stop) + + # Initialize the BusyLight objects + $MyBusyLight = New-Object -TypeName Busylight.SDK + } + + process + { + if ($pscmdlet.ShouldProcess('Busylight', 'Set Color')) + { + switch ($Color) + { + 'blue' + { + $null = ($MyBusyLight.Light([Busylight.BusylightColor]::Blue)) + } + 'cyan' + { + $null = ($MyBusyLight.Light(128, 255, 255)) + } + 'green' + { + $null = ($MyBusyLight.Light([Busylight.BusylightColor]::Green)) + } + 'magenta' + { + $null = ($MyBusyLight.Light(128, 0, 255)) + } + 'orange' + { + $null = ($MyBusyLight.Light(255, 128, 0)) + } + 'red' + { + $null = ($MyBusyLight.Light([Busylight.BusylightColor]::Red)) + } + 'white' + { + $null = ($MyBusyLight.Light(255, 255, 255)) + } + 'yellow' + { + $null = ($MyBusyLight.Light([Busylight.BusylightColor]::Yellow)) + } + 'off' + { + $null = ($MyBusyLight.Light([Busylight.BusylightColor]::Off)) + } + default + { + $null = ($MyBusyLight.Light([Busylight.BusylightColor]::Off)) + } + } + } + } + + end + { + # Cleanup + $MyBusyLight = $null + } +} + +function Set-bdcBusylightStatus +{ + <# + .SYNOPSIS + Wrapper function for Set-bdcBusylightColor + + .DESCRIPTION + Wrapper function for Set-bdcBusylightColor to set the color on a connected Kuando Busylight device + + .PARAMETER Status + The online Status you would like to set. + + Supported is: + - Available = green on the Kuando Busylight device + - AvailableIdle = green on the Kuando Busylight device + - Away = yellow on the Kuando Busylight device + - BeRightBack = yellow on the Kuando Busylight device + - Busy = red on the Kuando Busylight device + - BusyIdle = red on the Kuando Busylight device + - DoNotDisturb = magenta on the Kuando Busylight device + - Offline = Turn off the Kuando Busylight device + - PresenceUnknown = Turn off the Kuando Busylight device + + Based on this docs page: https://docs.microsoft.com/en-us/graph/api/resources/presence?view=graph-rest-beta + + .EXAMPLE + PS C:\> Set-bdcBusylightStatus -Status Available + + .LINK + https://docs.microsoft.com/en-us/graph/api/resources/presence?view=graph-rest-beta + + .LINK + https://docs.microsoft.com/en-us/graph/api/presence-get?view=graph-rest-beta + + .LINK + https://www.plenom.com/support/develop/ + + .NOTES + You will need the BusylightSDK.DLL, as the PowerShell scripts communicates with the device by calling functions in the DLL. + You can get it from the SDK, at https://www.plenom.com/support/develop/. + #> + + [CmdletBinding(ConfirmImpact = 'None')] + param + ( + [Parameter(Mandatory, HelpMessage = 'The online Status you would like to set.', + ValueFromPipeline, + ValueFromPipelineByPropertyName, + Position = 0)] + [ValidateNotNullOrEmpty()] + [ValidateSet('Available', 'AvailableIdle', 'Away', 'BeRightBack', 'Busy', 'BusyIdle', 'DoNotDisturb', 'Offline', 'PresenceUnknown', IgnoreCase = $true)] + [Alias('BusylightStatus')] + [string] + $Status + ) + + process + { + switch ($Status) + { + 'Available' + { + $null = (Set-bdcBusylightColor -Color green) + } + 'AvailableIdle' + { + $null = (Set-bdcBusylightColor -Color green) + } + 'Away' + { + $null = (Set-bdcBusylightColor -Color yellow) + } + 'BeRightBack' + { + $null = (Set-bdcBusylightColor -Color yellow) + } + 'Busy' + { + $null = (Set-bdcBusylightColor -Color red) + } + 'BusyIdle' + { + $null = (Set-bdcBusylightColor -Color red) + } + 'DoNotDisturb' + { + $null = (Set-bdcBusylightColor -Color magenta) + } + 'Offline' + { + $null = (Set-bdcBusylightColor -Color off) + } + 'PresenceUnknown' + { + $null = (Set-bdcBusylightColor -Color off) + } + 'default' + { + $null = (Set-bdcBusylightColor -Color off) + } + } + } +} + +#region LICENSE +<# + BSD 3-Clause License + + Copyright (c) 2021, enabling Technology + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#> +#endregion LICENSE + +#region DISCLAIMER +<# + DISCLAIMER: + - Use at your own risk, etc. + - This is open-source software, if you find an issue try to fix it yourself. There is no support and/or warranty in any kind + - This is a third-party Software + - The developer of this Software is NOT sponsored by or affiliated with Microsoft Corp (MSFT) or any of its subsidiaries in any way + - The Software is not supported by Microsoft Corp (MSFT) + - By using the Software, you agree to the License, Terms, and any Conditions declared and described above + - If you disagree with any of the terms, and any conditions declared: Just delete it and build your own solution +#> +#endregion DISCLAIMER diff --git a/Powershell/PowerShell-collection/bdcBusylight/readme.md b/Powershell/PowerShell-collection/bdcBusylight/readme.md new file mode 100644 index 0000000..34bd363 --- /dev/null +++ b/Powershell/PowerShell-collection/bdcBusylight/readme.md @@ -0,0 +1,81 @@ +# Kuando Busylight handler + +bdcBusylight is my new pet project. Goal of bdcBusylight is to set the color of a connected Kuando Busylight based on the status of my Microsoft Teams Rooms (MTR) System. + +## What is it + +For now, only the following two functions are published: + +**Set-bdcBusylightColor** +*Set the color of a connected Kuando Busylight device* + +**Set-bdcBusylightStatus** +*Wrapper function for Set-bdcBusylightColor to set the color on a connected Kuando Busylight device* + +### What is not published (yet) + +I use a Microsoft Graph call to get the current status of my Microsoft Teams Rooms (MTR) System. I still have some issues with the Microsoft Graph Module, so I still use some handcrafted RESTful calls (based on the `Invoke-RestMethod` command). As soon as I get everything working as expected, I will remove all hard coded parts and I will create functions for it. + +### Platform + +For now just Windows. I have a mini PC that runs Windows, and bdcBusylight should run on a Microsoft Teams Rooms (MTR) System. +To make it more flexible, I will try to bring support for Linux. That would make it easier to use Single-Board-Computer (SBC) solutions like a Raspberry Pi, or others. + +## Samples + +Here are some Examples of the functions. + +### Set-bdcBusylightColor + +```powershell +Set-bdcBusylightColor +``` +Turn the Busylight off. + +```powershell +Set-bdcBusylightColor -Color green +``` +Set the Busylight color to green. + +Please see the help: + +```powershell +Get-Help Set-bdcBusylightColor +``` + +### Set-bdcBusylightColor + +```powershell +Set-bdcBusylightStatus -Status Available +``` +Set the Busylight color to green, based on the status of a Microsoft Teams user. + +Please see the help: + +```powershell +Get-Help Set-bdcBusylightStatus +``` + +## Requirements + +You will need the BusylightSDK.DLL, as the PowerShell scripts communicates with the device by calling functions in the DLL. +You can get it from the SDK, at https://www.plenom.com/support/develop/. + +Windows! At least for now. I use the BusylightSDK.DLL and this will require Windows. + +## License + +### BSD 3-Clause License + +Copyright (c) 2020, Joerg Hochwald +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.