Monday, February 19, 2018

Why Isn't This Cmdlet Working?

Last week I was working on a script that creates a list of scheduled tasks on all of our remote servers.  I wanted the script to create the list using Export-CSV.  However, everything I ran the script I would get the error:
The term 'Export-CSV' is not recognized as the name of a cmdlet

Export-CSV is not recognized!?  I have been using this for years!

I did some research and found out that some minor versions of Powershell Version 2 did not include Export-CSV.  In order to correct this it was necessary to update the version of Powershell.

How can you check the version of Powershell?  Use the following script to get the Powershell versions on all your servers:
$adServers = $()

$adServers += get-adcomputer -Filter * -Properties * -SearchBase "OU=Servers,DC=abc,DC=com" |Select-Object Name

foreach ($server in $adServers) {

 Invoke-Command -ComputerName $server.Name -ScriptBlock { $PSVersionTable.PSVersion } | export-csv -append C:\PSVersionsbyServer.csv

}

Updating Powershell is very simple but will require a reboot.  Go here to get the Powershell update.  This is version 5 and called WMF 5.  Be sure to following the prerequisites.

Again, the update will require a reboot.

Having to update the one server, so Export-CSV will work, brought up the need for my company to make sure all of our servers are running a consistent version of Powershell.  If you have a lot of servers to update, make sure you have a solid plan and communicate the changes to your user base.

I hope this information was helpful.  Good luck.

Wednesday, February 14, 2018

Script To Get Version of Powershell

Hello again!

I have time today to add another post on this blog.  This script is what I use to get a list of all servers and what version of Powershell is installed on the server.

We are using this script to determine which servers will need to be updated to version 5:

$adServers = $()

$adServers += get-adcomputer -Filter * -Properties * -SearchBase "OU=ou1,DC=abc,DC=com" |Select-Object Name

$adServers += get-adcomputer -Filter * -Properties * -SearchBase "OU=ou2,DC=abc,DC=com" |Select-Object Name

foreach ($server in $adServers) {

Invoke-Command -ComputerName $server.Name -ScriptBlock { $PSVersionTable.PSVersion } | export-csv -append C:\PSVersionsbyServer.csv



}


As in other posts, I defined a variable called $adServers to hold the names of servers.  There are two OUs that contain server information.  That is why I have two get-adcomputer statements. 

In the FOREACH loop, I used Invoke-Command to query each server for the Powershell version.  I like using Invoke-Command because is saves from having to do a lot of extra coding such as creating and entering PSSessions.
 

Exporting variables to Export-CSV

Greetings!

I was asked to create a data feed (a text file) that contained the following information from Active Directory:
Employee Number
Employee Email Address
The last part of the employee's ObjectSID
Employee Login

Getting the information was relatively simple.  Since the information was in three different Organizational Units (OUs), I had to run 3 separate Get-ADUser statements, as follows:

$ouUsers = $()

$ouUsers += get-aduser -Filter { objectClass -eq "user"} -Properties * -SearchBase 'ou=ou1,dc=abc,dc=com' | Where-object {$_.Enabled -eq "True" -AND $_.employeeid -ne $null } | Select-Object employeeid,samAccountName,objectSID,EmailAddress  #| export-csv -NoTypeInformation rwsc_info.csv

$ouUsers += get-aduser -Filter { objectClass -eq "user"} -Properties * -SearchBase 'ou=ou2,dc=abc,dc=com' | Where-object {$_.Enabled -eq "True" -AND $_.employeeid -ne $null } | Select-Object employeeid,samAccountName,objectSID,EmailAddress  #| export-csv -NoTypeInformation rwsc_info.csv

$ouUsers += get-aduser -Filter { objectClass -eq "user"} -Properties * -SearchBase 'ou=ou3,dc=abc,dc=com' | Where-object {$_.Enabled -eq "True" -AND $_.employeeid -ne $null } | Select-Object employeeid,samAccountName,objectSID,EmailAddress  #| export-csv -NoTypeInformation rwsc_info.csv



Note: be sure to have the $ouUsers = $() statement or the variable will continue to grow since the  script uses += for each get-aduser statement.

Once I had all the information in the $ouUsers variable I create a FOREACH loop:
foreach($ouUser in $ouUsers)

It is within this loop I did two things:
1. Collect the last section of the ObjectSID
    Since the ObjectSID is separated into 8 parts (separated by a '-') I used the following code:
         $sid = $ouUser.objectSID # This puts the information into a separate variable
         $empSID = $sid.Value.Split('-',8)[7] # the '-' is the separator.  '8' tells how many array items.  # '[7]' is the last item in the array (array items start at [0])     

2. Export the information to the CSV file
    This was the section that took me the longest to figure out.  I though all I had to do was gather all
    the information into another variable and then export the data to a file (i.e., $data | Export-CSV
    c:\documents\datafile.csv).  This did not work.  All I got was the length of each variable.

   I did some research and found the following solution:

       [pscustomobject]@{

        EMPLOYEEID = $ouUser.employeeid

        EMAILADDRESS = $ouUser.EmailAddress

        SINGLESIGNON = $empSID

        NETWORKLOGON = $ouUser.samAccountName

       } | export-csv -append -NoTypeInformation datafile.csv


The full FOREACH loop is as follows:
      foreach($ouUser in $ouUsers) {

        $sid = $ouUser.objectSID

        $empSID = $sid.Value.split('-',8)[7]


  
       [pscustomobject]@{

          EMPLOYEEID = $ouUser.employeeid

          EMAILADDRESS = $ouUser.EmailAddress

          SINGLESIGNON = $empSID

          NETWORKLOGON = $ouUser.samAccountName

        } | export-csv -append -NoTypeInformation datafile.csv

      }  

As I said, getting the data to a CSV file took me a few hours to figure out.  I was able to find the solution on the StackOverflow web site (http://stackoverflow.com).

Let me know if you have any questions regarding this script.

See you soon,
Mike