Advanced Windows PowerShell Scripting Video Training

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

Sunday, August 30, 2009

List of all VBScript error codes.

In class we talked about the ability to handle errors in our scripts. The question came up as to how many potential error codes there are. Run the script below to find out. Remember that the function your are attempting to provide error handling for will not be capable of generating all these errors. You only need to script against the most likely ones, and then a catch all for anything unusual that pops up. This script uses a method that we did not talk about in class, Err.Raise. You use Err.Raise followed by the error number that you are interested in to help you test your error handling. This will cause your script to believe that the error actually occurred and invoke your error handling.

Dim errDef, i

WScript.Echo "VBScript-Errors:"
WScript.Echo "Number", "Description"

On Error Resume Next
Err.Raise 1
errDef = Err.Description

For i=1 to 2^16-1
Err.Raise i
If Err.Description <> errDef Then
WScript.Echo Left(Err.Number & ":" & Space(6), 6), Err.Description
End if


Thursday, August 27, 2009

If you upgrade a 2003 domain to a 2008 domain, are OUs protected from deletion?

OU deletion protection allows you to prevent the deletion of accidental move of an OU. This is a particular problem with using a laptop with a tiny mouse pad for administration. It is easy to accidently move an OU into another OU. With Group Policy, this can easily create problems. In Windows Server 2008, All OUs are created with the new OU Deletion Protection turned on by default. The question is, are OUs created on a Windows 2003 Domain protected after an upgrade to a Windows 2008 domain?

The answer is no.

I tested using a Windows 2003 domain created in a Hyper-V environment. I creaed an empty OU and another one with both a user account and a group. OU protection was not on by default for both of them after the upgrade. Also the objects inside the did not have deletion protection. To activate Deletion protection:

· Open AD Users and Computers

· Click View and select Advanced Features.

· Right click the OU and click Properties

· In the Object tab check Protect object from accidental deletion.

You will have to also do this for each object inside the OU that you want to protect.

Tuesday, August 25, 2009

How to install the 2008 admin tools on Windows XP?

The adminpak for Windows Server 2008 (RSAT) will not run on Windows XP. In our test environment, we configured:

  • Windows Sever 2008 R2 Domain controller
  • Windows Server 2003 member server
  • Windows XP SP2

We copied the adminpak.msi file from the 2003 server and installed it on the XP client. We were able to create an OU, Group, and User account on the 2008 domain controller without any issues. The RSAT program is not part of server 2008 like the adminpak was for 2003. You will need to download it from Microsoft.

Microsoft Remote Server Administration Tools for Windows Vista

PowerShell: Parse the events of the last 24 hours and color code them.

The following script demonstrates how to read events for an event log that have occured over the past 24 hours and to color code them. Now, use your imagination. With a little enginuity, you could parse for events that you are interested in and have this script exercise some procedures as opposed to just displaying colored text on your monitor. PowerShell is desighed for you to be able to create the tools that you need.

# ==================================================================
# EventColors.PS1
# Author: Jason A. Yoder, MCT
# Demonstrates how to list events from an event log written
# in the last 24 hours and also adding color to denote the event
# type.
# ==================================================================

# Get the current date and subtract 1 day. This is used to determine if
# an event is less the 24 hours old.
$Date = (get-date).adddays(-1)

# Gather the details of all event from the "System" log that are
# less then 24 hours old.
$Events = Get-EventLog -LogName "System" | where {$_.TimeWritten -gt $Date}

# Sent a number to represent which record we are looking at.
# This will be used in the DO WHILE loop to determine when to
# terminate the loop.
$EventNumber = 1

# The Switch statement is similar to the "case" statements
# in other programing languages. In this switch
# statement, we are evaluating what type of
# event has been recorded so we can give the event
# the correct color. Event Types include: Critical,
# Error, Wrning, and Information. Verbose is also
# a valid event type, but not included in this script.
Switch ($Events[$EventNumber].EntryType)
# The parameters of -ForgroundColor and -BackgroundColor will help
# distinguish each event type. Only the first line will have color
# attributes set. The remaining line of data for each event will
# go back to the values set as default for that user.
{ Write-Host -ForegroundColor Red -BackgroundColor DarkRed "Critical Messages"
Write-Host $Events[$EventNumber].EventID
Write-Host $Events[$EventNumber].TimeGenerated
Write-Host $Events[$EventNumber].MachineName
Write-Host $Events[$EventNumber].Message }
{ Write-Host -ForegroundColor Red -BackgroundColor DarkYellow "Error Messages"
Write-Host $Events[$EventNumber].EventID
Write-Host $Events[$EventNumber].TimeGenerated
Write-Host $Events[$EventNumber].MachineName
Write-Host $Events[$EventNumber].Message }
{ Write-Host -ForegroundColor Yellow -BackgroundColor DarkYellow "Warning Messages"
Write-Host $Events[$EventNumber].EventID
Write-Host $Events[$EventNumber].TimeGenerated
Write-Host $Events[$EventNumber].MachineName
Write-Host $Events[$EventNumber].Message }
{ Write-Host -ForegroundColor Green -BackgroundColor DarkGreen "Informtion Messages"
Write-Host $Events[$EventNumber].EventID
Write-Host $Events[$EventNumber].TimeGenerated
Write-Host $Events[$EventNumber].MachineName
Write-Host $Events[$EventNumber].Message }
# Incriment the record number pointer.
$EventNumber ++
# Conintue looping until the Record pointer is equal
# to the number of events in the event log.
} While ($EventNumber -le $Events.Count)

Sunday, August 23, 2009

VBScript Code for Excel formatting

VBScripting is capable of providing us will enormous amounts of information. The problem that we with VBScript is how to present that information? One way to do this is to use MS Excel to display our output. The following lines of code will open an Excel workbook. It will then enumerate and display some of the potential property values for borders in Excel. By looking through this script, you will get an idea of how to format the cells, enter data, and selecting the cell that you want to place data in.

' =============================================================================
' Boarder1
' File: Border1.vbs
' Author: Jason A. Yoder
' Version 1.0 Status: Completed
' -----------------------------------------------------------------------------
' Test script for Creating boarders in Excel.
' =============================================================================

' == Main Code ==============================================================
Set objExcel = CreateObject("Excel.Application")

' Open the spreadsheet

' Worksheet Title

' Border Thickness

' Border Position

' Line Style

' Line Color

' == End Main Code ==========================================================

' ++ Procedures +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++ OpenExcelWorksheet +++++++++++++++++++++++++++++++++++++++++++++++++++++
' Opens the spreadsheet specified in the variable 'TargetWorksheet'.
Sub OpenExcelWorksheet

objExcel.Visible = True

End Sub ' OpenExcelWorksheet
' ++ End OpenExcelWorksheet +++++++++++++++++++++++++++++++++++++++++++++++++

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sub WorksheetTitle
' Creates a page title
objExcel.Cells(1,1).Value = "Excel Cell Formatting Referance Chart"
objExcel.Cells(1,1).Font.Size = 20
End Sub ' WorksheetTitle
' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sub BorderThickness
' Creates borders of various thickness
objExcel.Cells(2,2).Value = "Weight"
For X = 3 to 6
'Set objRange = ObjExcel.Range(1,1)
ObjExcel.Cells(X,2).Borders.Weight = X - 2
ObjExcel.Cells(X,2).Value = X - 2
Next ' X
End Sub ' BorderThickness

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sub BorderPosition
' Creates borders at different positions
objExcel.Cells(2,4).Value = "Posiitons"
Y = 1
For X = 3 to 26 Step 2
'Set objRange = ObjExcel.Range(1,1)
ObjExcel.Cells(X,4).Borders(Y).Weight = 2
ObjExcel.Cells(X,4).Value = Y
Y = Y + 1
Next ' X
End Sub ' BorderPosition
' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sub LineStyle
' Changes the line style
objExcel.Cells(2,6).Value = "Style"
Y = 1
For X = 3 to 28 Step 2
'Set objRange = ObjExcel.Range(1,1)
ObjExcel.Cells(X,6).Borders(9).Weight = 2
ObjExcel.Cells(X,6).Borders(9).LineStyle = Y
ObjExcel.Cells(X,6).Value = Y

Y = Y + 1
Next ' X
End Sub ' LineStyle
' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Sub LineColor
' Changes the line color
objExcel.Cells(2,8).Value = "Color"
Z = 0
For X = 8 to 11
For Y = 3 to 29 Step 2
'Set objRange = ObjExcel.Range(1,1)
ObjExcel.Cells(Y,X).Borders(9).Weight = 4
ObjExcel.Cells(Y,X).Borders(9).ColorIndex = Z
ObjExcel.Cells(Y,X).Value = Z
Z = Z + 1
Next ' Y
Next ' x
End Sub ' LineStyle
' +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' ++ End Procedures +++++++++++++++++++++++++++++++++++++++++++++++++++++++++

' == End of Script ==========================================================

Friday, August 21, 2009

New class added: 50025 PowerShell for Administrators

After a few requests, I'm finally adding PowerShell into my class lineup. Some of you have already noticed that I'm posting PowerShell tips on Tuesdays. I figured that it is time to start teaching it as well. I've been writing administrative scripts for 5 years now. PowerShell is a clear improvement on VBScript. In one of my future Tuesday postings you will see how a 75 line VBScript was written in just 6 lines in PowerShell. Now that is something!

In this class we will look at some key aspects to get you off and scripting in PowerShell. We will cover the environment, Syntax and logic, and how to make your life a little bit easier.

I'll be instructing this class on September 9th 2009 at ENS Group in Fort Wayne, IN. Give Dave Shriner a call and let him you are interested in this three day class.

Thursday, August 20, 2009

How do you change the network interface name on Server Core?

To do this we are going to use the netsh command. By Default, Windows starts naming the network interfaces “Local Area Connection”. There are situations in which you may want to change this. Let’s say you have more than one network interface on your system. Maybe you use one for domain isolation. In other words. You can only talk to a set of servers on this interface that is secured with IPSec. This is a common scenario for domain controllers. To help you identify which interface you are working on, you can rename it.

Netsh interface set interface name=”Old Name” newname=”newname

For example, lets take the default interface and give it a new name.

Netsh interface set interface name=”Local Area Connectionnewname=”DCIsolation”

In the above example, we changed the default name of Local Area Connection to DCIsolation.

Wednesday, August 19, 2009

What is the default tombstone value for computer accounts in Windows Server 2008?

At one point, the tombstone value for Microsoft networks was 60 days. The problem with that is that prestaged computers did not always make it from the factory to being joined on the domain in time. For that reason, Microsoft started to change the tombstone value to 180 days. Here are two guidelines to help you determine the tombstone value:

  • On a domain controller in a forest that was created on a domain controller running Windows Server 2003 with Service Pack 1 (SP1), Windows Server 2003 with Service Pack 2 (SP2), Windows Server 2008, or Windows Server 2008 R2, the default value is 180 days.
  • On a domain controller in a forest that was created on a domain controller running Windows 2000 Server, Windows Server 2003, or Windows Server 2003 R2, the default value is 60 days.

To absolutely know, follow this procedure on your Windows 2008 domain controller:

1. Click Start, point to Administrative Tools, and then click ADSI Edit.

2. In ADSI Edit, right-click ADSI Edit, and then click Connect to.

3. For Connection Point, click Select a well known Naming Context, and then click Configuration.

4. If you want to connect to a different domain controller, for Computer, click Select or type a domain or server: (Server | Domain [:port]). Provide the server name or the domain name and Lightweight Directory Access Protocol (LDAP) port (389), and then click OK.

5. Double-click Configuration, CN=Configuration,DC=ForestRootDomainName, CN=Services, and CN=Windows NT.

6. Right-click CN=Directory Service, and then click Properties.

7. In the Attribute column, click tombstoneLifetime.

8. Note the value in the Value column. If the value is , the default value is in effect as follows:


Tuesday, August 18, 2009

PowerShell: What if I do this???

In PowerShell we have the ability to see what a command will do before it executes. Image when you were first starting out in IT. Someone told you to type Format C: without telling you the results. Obviously formatting the C: drive is not something you want to do on accident. You can ask PowerShell what would happen if you did _______. We use the -WhatIf parameter.

Let's first get a list of all services running on you client:

You noticed that a process is called BlueToothHeadsetProxy is listed. What would happen if you typed:
Stop-Process -ID 5200
(5200 is the process ID )

You would disconnect your headset. We can use the -Whatif parameter to discover what would happen if we would execute this command without executing it. To do this type:
Stop-Process -ID 5200 -whatif

stop-process -id 5200 -whatif
What if: Performing operation "Stop-Process" on Target "BluetoothHeadsetProxy (5200)".

We can also confirm each step before it is taken:
Stop-Process -ID 5200 -confirm

Are you sure you want to perform this action?
Performing operation "Stop-Process" on Target "BluetoothHeadsetProxy (5200)".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help
(Default is "Y")

The Suspend option has its value when you are typing a long command, but then remember that something else needs to be done first. By adding the -Confirm parameter, you can suspend the execute. This gives you a chance to complete the missed step and then to use the up arrows to retrieve the long command and execute it without having to retype it.

Sunday, August 16, 2009

UTC Conversion Code

When working with Date/Time functions in the WMI environment, we need to remember that this data is given to us in UTC time. For example, the date 2/25/2008 10:07:08 PM is formatted as 20080225220708.000000-300. Below is a function that will translate this UTC time into the conventional formatting for date/time. The time being feed is the OS installation date/time for the client running the script.

strComputer = "."
Set objSWbemServices = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colOS = objSWbemServices.ExecQuery("SELECT * FROM Win32_OperatingSystem")
For Each objOS in colOS
Wscript.echo WMIDateStringtoDate(objOS.InstallDate)

Function WMIDateStringToDate(dtmInstallDate)
WMIDateStringToDate = CDate(Mid(dtmInstallDate, 5, 2) & "/" & _
Mid(dtmInstallDate, 7, 2) & "/" & Left(dtmInstallDate, 4) _
& " " & Mid (dtmInstallDate, 9, 2) & ":" & _
Mid(dtmInstallDate, 11, 2) & ":" & Mid(dtmInstallDate, _
13, 2))
End Function

Friday, August 14, 2009

Event Subscription procedure that actually works.

I have been very frustrated with Microsoft’s Event Subscription procedure. First of all, it does not work. I have tried many times and cannot get past the part where you add the collector computer account to the local administrators group on the sender computer. I even watched a video from Microsoft that did everything but showed you that it worked. Below is my Event Subscription procedure.


The test environment is in a Windows 2008 R2 Hyper-V environment.


MCT-DC1 : Windows Server 2008 R2 Domain controllers – Will be the collector.

MCT-Core-1 : Windows Server 2008 Core

MCT-SRV-1 : Windows Server 2008 member server

The prep work:

First off, we need to use a service account. When creating a service account, I recommend a long, complex password. We will be setting the password not to expire so having a long and complex password will help with security.


· Open Active Directory Users and Computers.

· Create a user account inside Managed Service Accounts.

o If you do not have this OU, create the user account where appropriate for your domin.

o Username: EventCollector

o Password: Pa$$w0rd (please use a very cryptic password in your environment.)

o Uncheck User must change password at next logon.

o Check Password never expires.

o Click Next.

o Click Finish.

Now we must prep the firewall on each computer that will be sending events. In this exercise, MCT-Core-1, and MCT-SRV-1 will be our senders. The winrm quickconfig command that we will be executing will create an WinRM listener on each client.

On all the computers:

· Click Start

· Type CMD

· Press Enter

· Type winrm quickconfig and press Enter.

· Press Y when prompted.

On the Server Core:

We also need to execute an additional command on the collector (MCT-DC1) to configure the Windows Event Collector Service.

· In the command prompt window, type wecutil qc.

· Press Y when prompted.

We now need to add the service account to the Event Log Readers group.

On your Windows Server 2008 member servers:

· Click Start.

· Right click Computer and click Manage.

· Server Manger will now open.

· Click Configuration à Local Users and Groups à Groups.

· Double click Event Log Readers

· Click Add.

· Enter the name of your service account.

· You may be asked for domain admin credentials.

· Click OK twice.

On server core:

· Type net LocalGroup “Event Log Readers” /add domain\service account

o Example: net LocalGroup “Event Log Readers” /add Wilderness\EventCollector

We can now ask for events to be forwarded to the collector.

On your collector (MCT-DC1)

· Click Start à Administrative Tools à Event Viewer.

· Click Subscriptions.

· If prompted about the Event Collector Service, click Yes.

· In the Action column, click Create Subscription.

· Provide a Name and a Description for this subscription.

We need to provide our credentials to the subscription:

· Click Advanced

· Select Specific User

· Click User and Password

· Enter in your service accounts credentials. The syntax is domain\user name.

· Click OK twice.

We are not going to select the computers that we want to receive events from:

· Click Select Computers

· Click Add Domain Computers.

· Add each computer that you want to receive events from. Remember, you need to complete the prep work at the beginning of this article for this to work. You can only enter one computer at a time. Click OK and the click Add Domain Computers to add more computers to the list. In our example, we will enter:


o MCT-Core-1

· Click OK

You can test the connectivity to the each sender one at a time by clicking the name of the sender and then clicking Test

A popup box with “connectivity test succeeded” will let you know the connection has been made.

It is now time to select the events that we want to receive.

· In the Subscription Properties window, click Select Events.

· Select the Event Level that you are interested in. Your choices are:

o Critical

o Warning

o Error

o Information

o Verbose

· For this example, select Information.

· Click the drop down box next to Event Logs

· Expand Windows

· Check Application

· Click OK twice

We will now verify the subscription.

· In the subscription window, right click the subscription that you created and click Runtime Status.

· This image below shows two good connections.

· Click Close.

Next we will generate an event in the application log on the two senders.

· On your senders type: EventCreate /L application /T information /id 50 /d “This is a test of the event subscription.”

· On your collector in the Event Viewer click Windows Logs à Forwarded Events.

· You should now see the two test messages.

Congratulations, you have now set up an Event Subscription.

The next question is what happened if the connection does not work? Try this commands:

To verify that the collector can talk with the source computer:

Winrm id /r: /a:none

To test the collectors credentials

Winrm id /r: /u: service account /p: password

Run this on the collector to see if the source computer has been registered.

Wecutil gr

Tuesday, August 11, 2009

What do you need to know about IIS for exam 70-290?

Exam 70-290 is not necessarily an IIS exam. Now, I can’t teach the questions that are on the exam, but I can direct you to additional resources. TechRepublic has an article about what to expect on the exam. The first link below is to that article and the second is what the article suggest you read about IIS 6.0 before you take the exam.

PowerShell: How to read data from a text file.

This is a simple, but yet very useful task for anyone who scripts, how to read data from a text file. We will be utilizing the Get-Content cmdlet for this task.

In VBScript, we first had to create an object from the FileSystemObject. We then used the GetFile method to set another object to point to the data file itself. Next we would open the data file and then set up code to read the data file one line at a time and display each line as it was read. Then we would close the the file.

In Powershell, we can get a simple display of the contents of a data file simply by typing:
Get-Content DataFile.txt where Data File.txt is the path and name of the file that we want to read.

Lets say you want to count the number of lines. In VBScript, we would set a variable to increment with each line of test. In Powershell we type in the comment below:
Get-Content DataFile.txt | Measure-Object.

Count : 7
Average :
Sum :
Maximum :
Minimum :
Property :

The text file sampled above has 7 lines of text.

If you only wanted to return the count:
Get-Content DataFile.txt | Measure-object -property count
Count : 7

Sunday, August 9, 2009

Enumerate all files in a folder.

The question in class was “How do I list all the files in a remote computer?” First off, make sure that you are a member of the Administrators group on the target machine. In the first line (strComputer=”.”), replace the period with the name or IP address of the target machine. In the third command, replace ‘C:\Windows’ with the target folder.
strComputer = "."

Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colFileList = objWMIService.ExecQuery _
("ASSOCIATORS OF {Win32_Directory.Name='c:\Windows'} Where " _
& "ResultClass = CIM_DataFile")

For Each objFile In colFileList
Wscript.Echo objFile.Name

Friday, August 7, 2009

How can I put events in the event log for testing?

Luckily there is a command lint tool that can be used to place custome events in both the Application and the System event logs. EventCreate will allow you to put test data into the logs.

Eventcreate /l application|system /t ERROR|WARNING|INFORMATION /id 1-1000 /d description
Here is an example

eventcreate / application /t information /id 51 /d "This is a test."

Give it a try.

Tuesday, August 4, 2009

Can Windows Server 2008 block websites in a GPO or otherwise?

This topic seems to be a question that many are asking on the internet, but not getting the answers that they want. Before we dive into this, I would consider using a third party filtering service for blocking web sites. One of the purposes of Group Policy is to make life easier for Network Administrators. By taking on the responsibility of choosing what are appropriate websites, you are opening up yourself for a lot of work. By using a filtering service, you are paying someone else to do the grunt work. Also, many will filter your email. Should you lose your email server, these services will cache your email and deliver it once your server is back online.

The following article tells you how to use group policy to control website access. This is not necessarily for server 2008, but it gives you guidance.

Others are utilizing ISA server. I have even found some that are using a HOST file that points websites that they want to block to This technique will require the replacement of the HOSTS files on all your clients and a way to update them. Again, think about using a third party for your web filtering.

Sunday, August 2, 2009

How to enumerate all the installed updates on a computer?

This script will come in handy in an environment where you do not have Windows Server Update Service (WSUS) installed.

Set objSession = CreateObject("Microsoft.Update.Session")
Set objSearcher = objSession.CreateUpdateSearcher
intHistoryCount = objSearcher.GetTotalHistoryCount

Set colHistory = objSearcher.QueryHistory(1, intHistoryCount)

For Each objEntry in colHistory
Wscript.Echo "Operation: " & objEntry.Operation
Wscript.Echo "Result code: " & objEntry.ResultCode
Wscript.Echo "Date: " & objEntry.Date
Wscript.Echo "Title: " & objEntry.Title
Wscript.Echo "Description: " & objEntry.Description
Wscript.Echo "Client application ID: " & objEntry.ClientApplicationID
Wscript.Echo "Server selection: " & objEntry.ServerSelection
Wscript.Echo "Service ID: " & objEntry.ServiceID
i = 1
For Each strStep in objEntry.UninstallationSteps
Wscript.Echo i & " -- " & strStep
i = i + 1
Wscript.Echo "Uninstallation notes: " & objEntry.UninstallationNotes
Wscript.Echo "Support URL: " & objEntry.SupportURL