Advanced Windows PowerShell Scripting Video Training

Advanced Windows PowerShell Scripting Video Training
Advanced Windows PowerShell Scripting Video Training

Wednesday, June 24, 2015

PowerShell Code That Write’s it’s Own Code

I know, sounds a bit out there, but it is possible.

My PowerShell Class this week took a question from PowerShell.com. I do this every once and a while so we can apply our newly acquired skill sets to real life situations. This time around we helped out an IT Pro who was importing a CSV file to modify user objects using the Set-ADUser cmdlet of the Active Directory Module for Windows PowerShell.

The problem that he was having is that the database that generated this CSV file would occasionally place a NULL value in one of the properties. If you hard code Set-ADUser with a parameter, but then feed it a NULL value, it errors. The same thing happens if you pipe in a NULL value. He needed help trying to fix this. So, we went into action. And generated the cmdlet below.

The cool part about this code is that we did not hard code anything with regards to sending data to Set-ADUser. We utilized Invoke-Expression to execute commands that the code generates live. We also did not know if the CSV file contained data that would not be valid for a user object. We handled this little issue the same way that we handled the NULL values in the CSV file. We captured the errors and did nothing with them. No harm, no foul. We used SamAccountName as our identity property. Just modify the code to fit the identity property that you are using. You must have access to the Active Directory module for Windows PoweerShell for this to work.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103 

 

Function Set-ADUserFromCSV

{

[cmdletbinding()]

Param(

   

    [parameter(Mandatory=$true,

    ValueFromPipeline=$true)]

    $UserData,

 

    [Switch]

    $PassThru

)

Begin {} # END: Begin Block

Process

{

    # Import the data.

    $Data = Import-Csv -Path E:\data.csv

 

    # Extract the valid Property names from the object.

    $Props = $Data[0] | GM |

        Where-Object MemberType -eq NoteProperty |

        Select-Object -ExpandProperty Name

 

    $Data | ForEach-Object {

        ForEach ($P in $Props)

        {

            # This is the part that writes its own code.

            $String = "Set-ADUser -Identity $($_.SamAccountName) -$P $($_.$P)"

 

            # Add PassThru is requested.

            If ($PassThru) {$String += " -PassThru"}

 

            Try

            {

                # This makes the magic work.

                Write-Verbose "Executing: $String"

                Invoke-Expression -Command "$String" -ErrorAction Stop

            } # End: Try Block

            catch

            {

                <#

                Two items can cause errors here.

                1. Your CSV file have a property that is not a valid property for

                   a user object.

                2. You have a NULL field in your CSV.

                This will simply ignore the error and keep going.

                #>

 

            } # END: Catch Block

 

        } # END: ForEach ($P in $Props)

    } # END: ForEach-Object

} # END: Process Block

End {} #END: END: Block

<#

.SYNOPSIS

Modifies user accounts.

 

.DESCRIPTION

Takes an object containing SamAccountNames and other properties and

applies it to user accounts if the user account exists and the

property is a valid property for Set-ADUser.

 

.PARAMETER UserData

This is the object containing the data to be used to modify

the user object.

 

.PARAMETER PassThru

Places the modified user object into the pipeline.

 

.EXAMPLE

Import-Csv -Path E:\data.csv | Set-ADUserFromCSV

 

Modifies user objects based on the data imported from a CSV file.

 

.EXAMPLE

Import-Csv -Path E:\data.csv | Set-ADUserFromCSV -Verbose -PassThru

 

Modifies user objects based on the data imported from a CSV file.

This also places the user object into the pipeline and displays

verbose information.

 

.NOTES

Requires the Active Directory PowerShell Module.

 

===============================================================================

== Cmdlet: Set-ADUserFromCSV                                                 ==

== Author: Jason A. Yoder                                                    ==

== Company: MCTExpert of Arizona                                             ==

== Date:    2015JUN24                                                        ==

== Copyright: All rights reserved.                                           ==

== Version: 1.0.0.0                                                          ==

== Legal: The user assumes all responsibility and liability for the usage of ==

== this PowerShell code.  MCTExpert of Arizona, Its officers, shareholders,  ==

== owners, and their relatives are not liable for any damages.  As with all  ==

== code, review it and understand it prior to usage.  It is recommended that ==

== this code be fully tested and validated in a test environment prior to    ==

== usage in a production environment.                                        ==

==                                                                           ==

== Does this code make changes: Yes                                          ==

===============================================================================

#>

} # END: Function Set-ADUserFromCSV

 

 

 

 

Wednesday, June 17, 2015

Use Group Policy Preferences to Disable the Windows 8 Initial Logon Animation

So in my Windows class this week, I was asked if it is possible to disable the initial logon animation on Windows 8. You know, that one where you have to connect to the Windows App Store and then have to move the mouse around. By some strange coincidence, I actually hade the Windows 8.1 GPO Registry spreadsheet up. I did a quick internet search to find the correct registry setting, but did not find it as a GPO setting.

Next up GPO preferences. Normally I would throw PowerShell into the mix, but this is one of those cases where I feel that a GPO is the better choice. You see, with PowerShell, I would have to contact the computer when it is convenient for both of us. In other words, when I am running the script and the client is online. With a GPO Preference, I make this change and the domain tells the client what to do when the client comes online.

The registry setting is

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System

The key is a DWORD of EnableFirstLogonAnimation. A value of zero (0) will disable it and a value of one (1) will enable it.

To set it up, make sure that your clients are in an OU instead of the default computer container. You can apply this GPO setting at the domain level as well. To start, create a GPO or use one that is already scoped to your needs.

Edit the GPO and navigate to Computer Configuration à Preferences à Windows Settings.

Right click Registry and then select New-Registry Item.

Match the settings below and click OK

image

The icon for this setting may appears as if it is an error or warning icon.

image

The yellow triangle actually means that this is an Update operation. An update will perform a Create operation if the key does not exists. Once this policy is applied, your users will not have to wait so long on their first log in.

Friday, June 5, 2015

Use PowerShell to get coordinates from BING.

As I am continuing to build my module to support Bing using PowerShell, I needed a way to send Bing a location and get its coordinates back.  I had to do some research and I found Kevin Pelgrim’s code to do just that.  I also wanted the geographic rectangle of the selected address so I did some re-coding and also changed the code to match my programming style.  Here is the end result. Check out the help file for details.  You may notice some word wrapping going on.  Especially in the items in purple.  You may need to remove carriage returns if you copy and paste this code from those lines.  The items in green are the start of those lines.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
1
Function Get-BINGCoordinates
{
       [CmdletBinding()]
       Param (
              [String]$Location,
              [String]$Key = "Enter Your key Here"
       )
      
    # Custom Object
       Function Get-BingCoordinates-Object
       {
              $Obj = New-Object -TypeName PSObject -Property @{
                     "Address" = $Null
                     "Latitude" = $Null
                     "Longitude" = $Null
                     "NELatitude" = $Null
                     "NELongitude" = $Null
                     "SWLatitude" = $Null
                     "SWLongitude" = $Null
                     "Found" = $False
              }
              $Obj.PSObject.TypeNames.Insert(0, 'BingMaps.Coordinates')
              Write-Output $Obj
       } # END: Function Get-BingCoordinates-Object
      
       # Code borrowed from Kevin Pelgrims.
    # https://kevinpelgrims.wordpress.com/2011/08/18/bing-maps-geocoding-in-powershell/
       $ws = New-WebServiceProxy -uri http://dev.virtualearth.net/webservices/v1/geocodeservice/geocodeservice.svc?wsdl
       $wsgr = New-Object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1ervice_geocodeservice_svc_wsdl.GeocodeRequest
       $wsc = New-Object Microsoft.PowerShell.Commands.NewWebserviceProxy.AutogeneratedTypes.WebServiceProxy1ervice_geocodeservice_svc_wsdl.Credentials;
       $wsc.ApplicationId = $key;
       $wsgr.Credentials = $wsc;
       $wsgr.Query = $Location;
       $wsr = $ws.Geocode($wsgr);
      
       # Populate the output object.
       $Obj = Get-BingCoordinates-Object
       $Result = $wsr.Results[0] # Used to shorten the property addresses below.
       $Loc = $Result.Locations[0] # Used to shorten the property addresses below.
       $BV = $Result.BestView[0] # Used to shorten the property addresses below.
       $Obj.Address = $wsr.Results[0].Address.FormattedAddress
       $Obj.Latitude = $Loc.Latitude
       $Obj.Longitude = $Loc.Longitude
       $Obj.NELatitude = $BV.NorthEast.Latitude
       $Obj.NELongitude = $BV.NorthEast.Longitude
       $Obj.SWLatitude = $BV.SouthWest.Latitude
       $Obj.SWLongitude = $BV.SouthWest.Longitude
      
       # If an exact match is found, then flag FOUND as $True.
       If ($Obj.Address -eq $Location)
       {
              $Obj.Found = $True  
       }
       Write-Output $Obj
<#
.SYNOPSIS
Returns coordinate information from BING.
 
.DESCRIPTION
Returns coordinate information from BING. This includes the geographic
rectangle for the specified item.
 
.PARAMETER Location
An address or location to get the coordinates for.
 
.PARAMETER Key
Your BING map key
 
.EXAMPLE
Get-BINGCoordinates -Location "Indianapolis, IN"
      
Returns the coordinate information for Indianapolis, IN
 
.EXAMPLE
Get-BINGCoordinates -Location "Grand Canyon National Park"
Address     : Grand Canyon National Park, AZ
Latitude    : 36.2985153198242
NELongitude : -111.613616943359
NELatitude  : 36.8462715148926
SWLongitude : -113.970611572266
Found       : False
SWLatitude  : 35.7507591247559
Longitude   : -112.792114257813
 
.NOTES
Thank you to Kevin Pelgrims for his post on accessing BING.
https://kevinpelgrims.wordpress.com/2011/08/18/bing-maps-geocoding-in-powershell/
===============================================================================
== Cmdlet: Get-BINGCoordinates                                               ==
== Author: Jason A. Yoder                                                    ==
== Company: MCTExpert of Arizona                                             ==
== Date: 2015JUN02                                                           ==
== Copyright: All rights reserved.                                           ==
== Version: 1.0.0.0                                                          ==
== Legal: The user assumes all responsibility and liability for the usage of ==
== this PowerShell code.  MCTExpert of Arizona, Its officers, shareholders,  ==
== owners, and their relatives are not liable for any damages.  As with all  ==
== code, review it and understand it prior to usage.  It is recommended that ==
== this code be fully tested and validated in a test environment prior to    ==
== usage in a production environment.                                        ==
==                                                                           ==
== Does this code make changes: NO                                           ==
===============================================================================
#>
      
} # END: Get-BINGCoordinates
 
Get-BINGCoordinates -Location "Grand Canyon National Park"