07 February 2017

How to bulk change Calendar permissions in Exchange 2013 using PowerShell

Let’s assume, that you want to let some group of users see each others calendars. Instead of instructing each user to change calendar permissions using Outlook, you can do it for them.

First lets try to see current permissions:

$users = Get-DistributionGroupMember groupname@contoso.com | select -ExpandProperty PrimarySmtpAddress
foreach ($user in $users)
{$folder = $user + ':\' + (Get-MailboxFolderStatistics $user | where foldertype -eq calendar).name
"------------------------------------------------------------------------------------------------"
$folder
Get-MailboxFolderPermission $folder
}


It will produce similar output:
image

To add permissions, you simply need to change the get cmdlet to add cmdlet:

$users = Get-DistributionGroupMember groupname@contoso.com | select -ExpandProperty PrimarySmtpAddress
foreach ($user in $users)
{$folder = $user + ':\' + (Get-MailboxFolderStatistics $user | where foldertype -eq calendar).name
"------------------------------------------------------------------------------------------------"
$folder

Add-MailboxFolderPermission $folder -User groupname@contoso.com -AccessRights reviewer
Set-MailboxFolderPermission $folder -User groupname@contoso.com -AccessRights reviewer
}

Add and Set are both present because if the permission is already present, then first command will fail. If you want to use default calendar permissions, the mailboxpermission cmdlets should have ‘-User Default’ in the middle. If you want to change calendar permissions on all users, then instead of get-distributiongroupmember you should use get-mailbox instead.

21 April 2016

How to get the neighboring computer to talk using psexec, PowerShell and System.Speech

Let’s assume, you have domain network and you are using domain admin to do the trick. Also the neighbors computer must be running quite fresh windows version (i tried windows 10 only, let me know when older ones also work).

First of all you need psexec from sysinternals to run something on other computer. http://live.sysinternals.com/ is one good starting point for getting that tool.

Next open your command prompt as the domain admin user and type the following command (yes, it is a one-liner):

psexec \\neighbor cmd /c powershell [Reflection.Assembly]::LoadWithPartialName('System.Speech');$object = New-Object System.Speech.Synthesis.SpeechSynthesizer;$object.Speak('i know what you did last summer')

where neighbor is the name of the neighboring computer and last string is the text to speak. After some waiting the neighboring computer should talk to the default audio device.

25 January 2016

PowerShell speed optimizing on Active Directory cmdlets

Lets imagine, you have a task to find some AD user accounts based on a criteria and perform a simple task for each of them. My case is to clear manager for all user accounts, where extensionattribute3 is not present. This needs to be done regularly. So the time spent on this task should be minimized.

Initial version took about 160 seconds to run:

Measure-Command {
$users = Get-ADUser -Filter * -Properties extensionAttribute3 | ? extensionAttribute3 -ne 'Nortal Employee'
$users | foreach {Set-ADUser $_.SamAccountName -Clear manager -WhatIf}
}

Lets try to eliminate users, who already have manager cleared and not clearing the manager for them. This run took about 20 seconds because, instead of thousands of users, only few hundred were actually touched:

Measure-Command {
$users = Get-ADUser -Filter * -Properties manager,extensionAttribute3 | ? extensionAttribute3 -ne 'Nortal Employee' | ? manager
$users | foreach {Set-ADUser $_.SamAccountName -Clear manager -WhatIf}
}

Next iteration would be piping all users directly to Set-ADUser cmdlet, but this would not work straight forward, we will need Select-Object with ExpandProperty. This run took about 5 seconds because Set-ADUser was loaded only once instead of hundred times:

Measure-Command {
$users = Get-ADUser -Filter * -Properties manager,extensionAttribute3 | ? extensionAttribute3 -ne 'Nortal Employee' | ? manager
$users | select -ExpandProperty SamAccountName | Set-ADUser -Clear manager -WhatIf
}

Get-ADUser will still get all users and the filtration is done in PowerShell. This can be optimized to pass LDAP query to AD to return only needed user accounts. This run took about 2 seconds:

Measure-Command {
$users = Get-ADUser -LDAPFilter "(&(manager=*)(!extensionAttribute3=*))"
$users | select -ExpandProperty SamAccountName | Set-ADUser -Clear manager -WhatIf
}

This command can be converted to oneliner. This will have no noticeable effect on command duration, but looks perhaps cleaner:

Measure-Command {Get-ADUser -LDAPFilter "(&(manager=*)(!extensionAttribute3=*))" | select -ExpandProperty SamAccountName | Set-ADUser -Clear manager -WhatIf}

So our initial code was later optimized to to run nearly 100 times faster. Not a bad thing for a scheduled task running daily or hourly.

12 August 2015

Allow a specific port through Windows Firewall using PowerShell

By default Windows Firewall is turned on Windows Servers. Instead of turning off whole firewall you should allow only some ports go through. To do this using PowerShell you need only one simple line of code:

New-NetFirewallRule -DisplayName mssql -LocalPort 1433 -Protocol tcp

This example opens Microsoft SQL Server TCP port 1433 for incoming connections. Nice and easy line. Especially handy, when you need to do this using script on multiple servers.

To remove this rule, you should use the following command (mssql being the displayname of the rule):

Remove-NetFirewallRule -DisplayName mssql

11 August 2015

How to get your public IP in PowerShell

Ever wanted to know your public IP address programmatically in PowerShell? Here’s a good oneliner for you:

(Invoke-WebRequest http://myip.eu ).ParsedHtml.body.innerText.Split()[15]

It will get a sample page from myip.eu page, parse this html page body and find in text only version a space splitted part with serial number 15. No warranty though that this page work forever and the page result is formatted the same in future. Still worth a try.

02 February 2015

How to add domain user to local administrator group using PowerShell

All you need is following one-liner:

([ADSI]"WinNT://localhost/administrators,group").psbase.Invoke("Add",([ADSI]"WinNT://domain/user").path)

You need to change the domain/user to your actual domain name and user name (contoso/john for example).

05 January 2015

Get all sites and subnets in AD using PowerShell

I wondered if there is a command like Get-ADSite or Get-ADSubnet in PowerShell but it turns out there isn’t.

After surfing around the net I ended up writing this oneliner:


Get-ADObject -SearchB (Get-ADRootDSE).ConfigurationNamingContext -f { objectClass -eq "site" } -Properties * | ForEach-Object { ''; $_.Name; foreach ($s in $_.siteObjectBL) { $s } }


The output lists all sites separated by empty line. For each sites all subnets are listed.