Showing posts with label Powershell. Show all posts
Showing posts with label Powershell. Show all posts

Monday, 15 June 2015

Manipulating object tables in Powershell.

Last week I posted about creating object tables in Powershell. This was mainly for the purpose of being able to use Export-CSV to send the data out to a CSV file. This time I am going to have a brief look at some of the other things you can do with an object table, which is a convenient way of having a simple database that you can store data in and process it through your script.

Since the object table is basically an array of objects, it can be manipulated using the basic array operators. Such as:
  • Append an instance: += which most people will recognise as the standard increment operator borrowed from C/C++.
  • Retrieve an instance by index: e.g. $S[0] returns the first instance
  • Retrieve a range of instances by index e.g. $S[4..9], $S[1,2+4..9]
  • Retrieve the last instance: $S[-1] which is great as you don't need to know how big the array is to use this.
Obviously we don't need to use typical database methods like First, Last, Next and Previous which are often provided to step through a table's records. Instead just index the array.

Thursday, 11 June 2015

Creating object tables with Powershell

One of the useful things you get with Powershell is lots of functions that create data tables in memory that you can cycle through using Foreach to get an instance (equivalent to a record or row in a regular database) and then interrogate its properties (equivalent to columns). The Foreach loop automatically steps through all the object instances in the table.

Having done a number of function calls (for example Import-CSV to get a list of users from a CSV file, or Get-ADUser with a search spec to retrieve a bunch of user accounts) I thought it was about time I worked out how to create an object table myself, so that I could populate it with some user account data and then write it all out to a CSV file, using Export-CSV in this case. 

Well it turned out to be exceptionally simple to do this. Basically, object tables are just arrays of objects. Here is some code to illustrate this.

$UserList = @()
foreach ($Class in $Classes)
{   
$ADStudents = Get-ADUser -Filter  {Division -eq $Class} -SearchBase  "ou=Students,ou=School,dc=our,dc=school" -SearchScope Subtree -Properties ipPhone   
if ($ADStudents -ne $null)   
{ 
         foreach ($S in $ADStudents)
        {           
$username = $S.samAccountName           
$pwd = $S.ipPhone           
if ($pwd -eq $null)           
{               
    $pwd = ""           
}           
$UserList += New-Object psobject -Property @{Class = $($Class);Username=$($Username);Password=$($pwd)
}        
}   
}
}
So in this script, which loops through a set of classes ($Classes is an array of names of classes) the first line is to create the table itself, with no rows and no columns just yet. This is the simple $UserList = @() call which is actually creating an array.

Then the first Foreach loop is to go through a predefined array of class names for the school, and it gets the name of the current class into $Class. Then it gets all of the student accounts which have that class specified in their Division property. Note that it also retrieves the IpPhone property, which is used to store the passwords that we want to have a list of.

So the next step is to find out if we retrieved any results, and if so, another foreach loop has the task of getting each instance in turn (because the results of the Active Directory call are returned in an object table themselves) and then we add a row or record to $UserList. Firstly we create an object instance in which to store the data, and then we specify that the properties of that instance are Class, Username and Password, and the values they contain. 

It's useful to note here there is no fixed structure for each row, because each row only needs to be an object, and each row could easily refer to a different object structure, with different property names. This is a key difference from a regular database which predefines column names and types so they are consistent throughout the dataset. Obviously I am keeping things simple here and making every object instance identical.

So that is how we create our table, and the final line of the script (not shown) is a simple call to Export-CSV to write out the table to disk. 

Thursday, 7 May 2015

Using Powershell to monitor AD account creation

http://community.spiceworks.com/how_to/76915-automatic-report-about-newly-created-user-accounts-to-an-e-mail

Here’s a neat article about how to monitor event logs on a domain controller that cause a script to run whenever a new user account is created. The main limitation I see is it will only work on the DC that the account was created on. We really need a generic one that will work on any DC. Other than that, it’s a great idea that I will do some testing on soon.

Saturday, 28 March 2015

Detecting file change management in PowerShell

For some time Windows has supported in the Win32 API various events that are triggered when files or directories in a filesystem are changed and this appears to be supported in .NET as well. This then leads us to a natural question of whether we can support that in PowerShell. Due to PowerShell being essentially a scripting extension to .NET, we indeed can use these capabilities in our scripts.

After looking on the internet it appears from several sources mentioned below I can have a script that looks something like this:
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $searchPath
$watcher.IncludeSubdirectories = $true
$watcher.EnableRaisingEvents = $true


Starting off here the FileSystemWatcher object is instanced for this script and parameters have been passed to define the path to be searched and whether to include subdirectories. The last line tells the FileSystemWatcher to raise an event when a change is detected. 


$changed = Register-ObjectEvent $watcher "Changed" -Action {
   write-host "Changed: $($eventArgs.FullPath)"
}
$created = Register-ObjectEvent $watcher "Created" -Action {
   write-host "Created: $($eventArgs.FullPath)"
}
$deleted = Register-ObjectEvent $watcher "Deleted" -Action {
   write-host "Deleted: $($eventArgs.FullPath)"
}
$renamed = Register-ObjectEvent $watcher "Renamed" -Action {
   write-host "Renamed: $($eventArgs.FullPath)"
}
This section registers the event handlers for different types of events that are raised. Once this piece of code has executed then these actions will be fired each time the FileSystemWatcher detects a notifiable activity.

Unregister-Event $changed.Id
Unregister-Event $created.Id
Unregister-Event $deleted.Id
Unregister-Event $renamed.Id
Finishing off here with unregistering the event handlers and there should also be a call to dispose of the $watcher object or at least disable it when no longer needed. Closing the PowerShell session will have the same effect.
The source for this script came from here: http://dereknewton.com/2011/05/monitoring-file-system-changes-with-powershell/

There is a comment to that article mentioning the Change event can be fired multiple times for the same file depending on how the application doing the change works with the file. To limit the firing of multiple events some other kind of code may be needed in an event handler to determine whether the file is currently opened or closed by the application which is writing to it. I still have to do some testing with the setup I am looking at to determine how these events would be fired and which events to use. An option is to have the creating script rename the file once it has finished with it and the rename event will then be fired.

Well, testing it works more or less as expected. One major issue to be aware of is to do with errors; the code inside the braces for the Action won’t be evaluated by the Powershell ISE for syntax errors and if a mistake occurs in execution the usual messages on the Powershell console window will not be displayed. So we really only have the option of live testing. The situation I am working with uses a script that causes an email to be sent to a group whenever the action files, so I will be watching for emails coming in for sure.