Powershell

Null and Not Null with PowerShell

Finding out if an object has a null (i.e. blank) value or not isn’t a difficult task to do.

Consider this scenario – you’ve found a bunch of old disabled accounts that someone forgot to remove the ‘Manager’ field. Finding accounts that have another field that would be populated for a current employee but blank for a departed would be a reasonable way of finding the problem accounts, then you could null the ‘Manager field. (note – you could just refine your search to disabled accounts but that’s not as fun).

To find all Active Directory users that have a blank ‘Department’ field is easily done with this command:

get-aduser -filter * -properties department | where department -eq $null

Then, showing the users that don’t have a blank ‘Department’ field is a slight change. You can’t use !$null (!=not), but you can use -ne (not equals)

get-aduser -filter * -properties department | where department -ne $null

You can also check for users that have a manger by switching ‘department’ to ‘manager’:

get-aduser -filter * -properties maanger | where manager -ne $null

Easy. Adding in a second ‘where’ statement so we can get results of users that have a manager, but no department means we have to add in a few extra characters to make PowerShell happy:

get-aduser -filter * -properties department,manager | where {($_.department -eq $null) -and ($_.manager -ne $null)}

The results can be a bit hard to read, so piping (|) to a select command will just show us the results of each user we want to see:

get-aduser -filter * -properties department,manager | where {($_.department -eq $null) -and ($_.manager -ne $null)} | select name

Finally, to blank the ‘manager’ field, we can swap the ‘select name’ command with this:

get-aduser -filter * -properties department,manager | where {($_.department -eq $null) -and ($_.manager -ne $null)} |  set-aduser -manager $null

You can then go back to a previous command to confirm you get no results. As always, check your data first before blanking out a bunch of user’s values!

Update

As @mickesunkan pointed out, the above isn’t the most efficient way to do searches. I’m sure I’ve mentioned this before, but I’m not always going to write the cleanest, quickest way of doing something. For a once off tasks this really doesn’t matter. For a daily task it starts to matter – not really by itself, but if you keep making more and more inefficient scripts, you’re putting extra unnecessary load on your environment with lots of LDAP lookups.

Above, I’m just getting ALL AD users. You could use a better filter and narrow down to a certain OU. You could also put part of your ‘where’ command into the filter, such as this:

get-aduser -properties manager,department -filter {department -notlike “*”}

This doesn’t work for the ‘Manager’ field though, you’ll see this error:

get-aduser : Operator(s): The following: ”Eq’, ‘Ne” are the only operator(s) supported for searching on extended attribute: ‘Manager’.

I couldn’t work out a way of putting the $null value as part of the filter, but if you do – please share :)

 

@mickesunkan also wrote this github code showing a few differnet ways to do this search, and which way is most efficient. Thanks Micke!

 

 

 

Search Group Policy with PowerShell Script

I was looking for a certain Group Policy Preferences setting, where a registry value was being changed. Resultant Set Of Policy (RSOP) won’t help with these, and I couldn’t see a nice PowerShell command for searching through Group Policies.

I put the shoutout on Twitter to see who could help, and Tony Murray came back quickly with a script he’d created, and promptly uploaded to the Microsoft TechNet Gallery where I could download it.

It’s a reasonably simple script (which for me would have taken at least an hour to do beginning to end!) and is very easy to use.

Running the ps1 file will provide you with a prompt, asking what string you’re searching for. Enter the string, and it’ll give back all the Group Policy objects, along with if there was a match or not:

match

After seeing it work, I decided to make one slight change; I removed this section:

    else { 
        Write-Host "No match in: $($gpo.DisplayName)" 
    } # end else 

which results in the script only showing matches, and displaying no output otherwise. Handy if you have a long list of objects to look through!

Thanks again Tony for both writing this and sharing it!

 

Update 20th Dec 2018

Although the script is really useful, it didn’t like special characters for the search string which makes it hard to search for registry settings. I’ve changed how the search function works on a single line, and it now seems to be happy with special characters. This also appears to come at a cost of speed, it’s a bit slower to search. I’m letting Tony know so he can consider updating his master script, but if you want to do it, just replace the line:

if ($report match $string) {

with

if ($report.contains(“$string”) -eq $true) {

Again since it’s not my script I don’t really want to put the entire end result up, but here’s how it should look after the comments section:

Mass Import PSTs To Different Folders In A Single Mailbox

I had a scenario come up where someone had 50 or so PST files. I wanted to add them all into their mailbox, but have a separate folder for each PST’s contents to go to.

This was on Exchange 2010 SP3 but should apply to newer versions too, and this is assuming you have at least Exchange 2010 SP1 – importing was done differently before this.

For starers, ExchangeServerPro covers the basics of PST importing. PeteNetLive delves a bit deeper into batch importing, which was close to what I wanted but had to modify somewhat.

I had the PST files in a UNC path, so started by navigating there – in Powershell, you can just ‘cd //server/sharename/’ (even though “cd” is an alias for “Set-Location”, I can’t help but use it!)

Once in the share that contains the PST files (and it HAS to be a share, can’t be an admin $ share, and needs the correct permissions as per ExchangeServerPro’s article), you can run this command:

dir *.pst | %{ New-MailboxImportRequest -BatchName Recovered -Mailbox alias -name $_.BaseName -FilePath “$_.” -TargetRootFolder $_.BaseName}

This will get the list of files, and run a mailbox import request against each one. “alias” needs to be changed to the mailbox name. The Filepath is just being called as itself “$_.” and the Target Root Folder is using BaseName, which is the filename without the extension .pst.

I’m also using the filename as the name for the job, if you leave that out it’ll hit a wall after 10 jobs and want a unique name (if not specified, the name is MailboxImport, then MailboxImport1, MailboxImport2 etc and hits a wall at MailboxImport9). That also makes it easy if one of the jobs fail, to work out which PST was involved.

This worked really well for me, so hopefully it helps someone else out there!

WOL And Reboot Over Multiple Subnets With SCCM

Running a Wake On LAN can be tricky if you’ve got lots of subnets to worry about. A magic packet will only work in the local subnet unless you happen to have complete access to your entire network and make some router changes.

There’s also ‘Wake Up Proxy‘ which was added to Configuration Manager that can potentially work too as it’s peer to peer and clients try to wake each other up, but won’t work in a lot of scenarios such as 802.1X.

In light of these, I wrote a script that was a mashed up version of a few things I could find and accomplish the task of sending WOL packets to each subnet I cared about.

What this script does:

  • Pulls computers and in turn, MAC addresses from a pre-created SCCM collection.
  • Checks each computer to see if it’s online
  • If online, it will trigger a reboot countdown of 5 minutes, with a warning prompt
  • If offline, it will send a WOL magic packet to the computer

This is valuable to me for software installs that require no user logged onto a computer. It will leave all computers at the login screen, ready for software installs.

This only works in a single subnet though, so the next trick is to set this up on a server in each subnet as a scheduled task. Each server is configured to check the SCCM collection of computers that exist in that subnet. Then, a master task is created that calls the task on each of the other servers:

WOL

This master task triggers all the WOL scripts, on a schedule or on demand as you wish. You need to use an account that has access on all servers required of course to be able to remotely trigger the scheduled tasks.

I’ll also note that Adam Bertram wrote a different WOL script that will find each subnet and use any PC it can find to send WOL commands to other computers which is worth checking out. It doesn’t incorporate the forced reboot, but should be modifiable to achieve that result.

The script uses the free wol.exe program from Gammadnye and is expecting to run from C:\Scripts\ but you can change that to whatever you like without breaking anything.

Download the script here (rename to .ps1)

 

Start-Transcript -path C:\Scripts\Log\wolreboot.txt
$SiteCode = ‘SCCM Site Code goes here’
$CollectionName = ‘Target collection name goes here’
#Retrieve SCCM collection by name
$Collection = GWMI -ComputerName $siteServer -NameSpace “ROOT\SMS\site_$SiteCode” -Class SMS_Collection | where {$_.Name -eq “$CollectionName”}
#Retrieve members of collection
$SMSMembers = GWMI -ComputerName $SiteServer -Namespace “ROOT\SMS\site_$SiteCode” -Query “SELECT * FROM SMS_FullCollectionMembership WHERE CollectionID=’$($Collection.CollectionID)’ order by name” | select Name

ForEach ($SMSMember in $SMSMembers){
If (test-connection $SMSMember.Name -Count 1 -quiet)
{
write-host $SMSMember.Name “Online”
$name = $smsmember.name
Start-Process Shutdown “-r -t 300 -m \\$name -c `”Initiating scheduled maintenance reboot. You have 5mins to save your before your PC will reboot`”” -NoNewWindow -Wait
}
Else
{
$a = (GWMI -ComputerName $siteServer -Class SMS_R_SYSTEM -Namespace root\sms\site_$SiteCode | where {$_.Name -eq $SMSMember.Name}).MACAddresses
$a = $a -replace ‘:’,”
foreach ($mac in $a){

C:\Scripts\\wol.exe $mac
write-host $SMSMember.name “WOL packet sent” $mac
write-host `r`n}
}
}
Stop-Transcript

Exit

Update 9th August 2016

A few changes to the script – it’ll now log via transcript, but more importantly will support SCCM client objects with multiple MAC addresses, and broadcast each found MAC address.

Softerra Adaxes Identity and Active Directory Management Review

I’ve been asked to review many products (both hardware and software) on this blog. Many of the things I write about here are triggered by my experiences, which I think adds to the usefulness of the posts. Usually I decline, because I either don’t have an interest in the product, or don’t have the time to invest reviewing something that I can’t get a personal benefit out of the product in question.

Softerra Adaxes was one of these companies. After giving it a quick once over, my interest had been piqued. After extensive testing, I was actually happy to write a review of what the product does, and how I can see it helping people in businesses… so here is my take on the product. This is a sponsored post, but written by myself with my honest view on the product after extensive testing.

What is Softerra Adaxes?

First and foremost, this is an Active Directory (AD) Identity Management piece of software. It will talk to your AD environment (don’t worry, no schema changes required!) and give you a framework to allow automation. I’d previously looked at System Center Orchestrator (SCOrch) to look at the automation of user accounts such as creation, change, deletion – but it was too complicated for my liking. Most things required you to write your own code (PowerShell, .NET etc) and use what I’d call strange variable calls, instead of plain old nice code. To me, you have to wear a developer hat to use SCOrch for anything beyond very basic workflows.

Adaxes takes a different approach. Instead of writing your own code (which you can do still), much of it is driven in a similar way to how Outlook rules work. You can use the Adaxes Console, or Adaxes webpage to perform tasks such as ‘Create User’ – but you define the rules. For example, think of the ‘City’ field in AD. These are the rules you can set for it:

adaxes1
Those rules then end up as the only choices via a drop-down menu:
adaxes2

Having a default value if > 50% of your users are going to be in a particular city is a time saver. Same applies to being able to list several cities, and have a dropdown list to select them from – removing human error from typos. Forcing the property to being required also means it won’t be missed. To me, this gives immediate benefit in the user creation process, if the time is spent setting it up correctly.

User Creation in Adaxes

Once a user is created with your template, ‘Business Rules’ can kick in. These are more rules based on an event happening – such as a successful user creation. For me, I created business rules based on the City. If they’re in Sydney, then do all these things that applies to a Sydney person. This can be the creation of a home drive, but also can hook into Exchange or Lync to create their account in that environment too.

adaxes3

The Exchange and Lync integration allow you to have a user fully set up without even needing to worry about it. The email alias can be pulled from the username, and normal email address policies apply for creation of SMTP addresses. You can specify which DAG the mailbox will be created on too. For Lync, it’s the same story. If you’re lucky enough to have Enterprise Voice, the user’s phone number can be used as a variable to create a Line URI for the user.

Other third party systems can be manipulated by running a PowerShell script or program easily enough, or if you want to start getting tricky… there’s the Adaxes SDK for API.

When it’s all done, you can even trigger an email to alert staff that a user has been created, which could be used to alert other departments of any manual processes they need to do once a user is ‘born’.

Even better, is the easy built-in security roles. You can give HR access to create a user via the native Adaxes web page. No software required, HR follow the bouncing ball of the webpage and see a prompt for any required field, and requests can be configured to require approval before being actioned too.

https://www.youtube.com/watch?v=GlgVcGF7gjA

What Else Can Adaxes Do?

I’ve focused on User Creation so far, because that was the first benefit I saw from Adaxes – but there’s a bunch more this software solution can do. Softerra themselves list many of the features of the product, but it’s a very open framework where you can make the software do what you need to happen.

  • Group Management

Due to the granular security model they use, you could consider end user management of groups. Email group management for end users is already possible from Microsoft Exchange, but you can’t do the same with security groups. I can see a big benefit in letting key users manage a selection of security groups which could allow things such as access to network drives and folders, access to software or permissions to an internal resource such as a SharePoint site and so on. If you’re in a Microsoft environment, everything should be security based via AD groups anyway, so this is a much nicer solution than giving those key end users an Active Directory User and Computers console.

  • Password Expiration Notifcation

There are several built in examples of ‘Scheduled Tasks’ – including some I’ve written my own script for! The ‘Password Expiration Notifier’ does exactly what I wrote here, which is to notify end users via email when they have certain days left before their password expires. My preference is to have all of these tools and triggers in a central location where all the right people can see what’s going on with ease, which is better than having Windows based scheduled tasks scattered around your servers being harder to find and manage.

password

Although I encourage everyone to know PowerShell, the reality is we all have different skills and priorities. Having middle-ware that manages the smarts, and shows you in an easily readable format reduces company risk in both managing automation as well as staff time in making changes should be at least investigated for it’s potential value. The above example out of the box had only the 7 day notification, so I copied and pasted the rules below it, and set the trigger to also happen at 1 day, matching my script. That was 10 seconds of work.

adaxes4

  • Clean Up Old Computer Records

Another example of a built in Scheduled Task is the ‘Inactive Computer Deleter’. Simply, it does a daily check for computer objects to see if they’ve been inactive for more than 12 weeks. If true, it changes the ‘When Marked Inactive’ property of the computer to the current date and time. It won’t delete the computer until it has approval, and you can tell it who to get the approval from. Tasks like this should save you time as well as helping to secure your network from rogue devices.

  • Office 365 User Management

There is also Office 365 support, which can automate tasks such as user creation, or license management. At the time of writing, an Office 365 CAL can’t be auto assigned to an Office 365 user when synced from Active Directory, but Adaxes can automate that step for you.

Conclusion

To me, the above is enough of a business case to at least consider Softerra Adaxes. Some time needs to be invested to make the software do what you want to do – every businesses’ user management processes are different. If you’re currently using just a PowerShell script, you could use that from Adaxes and build the workflow and web interface management around it for starters, then migrate tasks to Adaxes as you find time.

I can’t find many weaknesses in this solution – there’s provision for resiliency by having more than one server, the product seems secure and stable. I would like to see more built in options on what you can do out of the box (to Softerra’s credit, there is a lot of options already and is highly configurable). I noticed that I couldn’t specify some extra parameters in Lync beyond the basics of user creation, such as which policies to apply to a user. This will have to be done by calling a PowerShell script I’d write instead.

There’s also a bit of a learning curve around applying security and using the interface – not that it’s difficult, and the online documentation is extensive, but you’ll need to do a bit of tutorial reading to understand the product and how to configure it to your liking.

I also really like the potential of giving end users control over certain things. Empowering users that make decisions to act on those decisions themselves is a time saver – as is having an incredibly easy workflow approval process that doesn’t need a complicated workflow engine and a team of developers behind the scenes.

Overall, I really liked the product and the direction they have taken it. I personally recommend checking it out, and am actually in the process of implementing it in my current workplace as a result of this review, as a paid product!

Other Adaxes videos are available on YouTube, along with pricing available on their website (there’s also a 30 day trial – install is very simple).