Read my contributions to The DSC Book
Hi guys,
I was honored when Don Jones contacted me, wanting to use my DSC post in ‘The DSC Book’, a free ebook available from PowerShell.org.
Continue Reading...Where can I run DSC?
You can run desired state configuration on any system which can run WMF 4.0.
From TechNet : ** Operating System Requirements Windows PowerShell 4.0 runs on the following versions of Windows. Windows 8.1, installed by default
Windows Server 2012 R2, installed by default
Windows® 7 with Service Pack 1, install Windows Management Framework 4.0 to run Windows PowerShell 4.0
Windows Server® 2008 R2 with Service Pack 1, install Windows Management Framework 4.0 to run Windows PowerShell 4.0
Windows PowerShell 3.0 runs on the following versions of Windows. Windows 8, installed by default
Windows Server 2012, installed by default
Windows® 7 with Service Pack 1, install Windows Management Framework 3.0 to run Windows PowerShell 3.0
Windows Server® 2008 R2 with Service Pack 1, install Windows Management Framework 3.0 to run Windows PowerShell 3.0**
Windows Server 2008 with Service Pack 2, install Windows Management Framework 3.0 to run Windows PowerShell 3.0 **
So, you can run DSC on anything down to Server 2008 and Windows 7.
Continue Reading...ADUC Tip - Easily edit Object Attributes directly from Search in Users and Computers
The problem
One of the bizarre pain-points of administering Active Directory Users and Computers is that you cannot edit Object attributes directly from Search. What do I mean about this? Here is an example. I’m searching for myself here.
I can see my object, but when I open it, I only see a subset of the available properties for the object. Notable missing is the ‘Attribute Editor’ tab.
Normally the next step is to look at the object path and browse out to it in AD, which wastes a lot of time. However, we’ll never waste that time again, once you’re armed with this tip!
[] I normally shudder more and more as I see how deep I have to search to find this object I need to edit.
[] Slogging all the way down into a deep or complex tree is one of those minor things that can make you hate your life.
The Fix
We’ll not do it the old way again. So, from the Search window, find your user or computer you’d like to alter, then click Member Of. Open one of the groups the object is in and then close the original object window.
[] Click ‘Member Of’ for the object you’d like to edit, then pick a group that contains them.
[] Be sure to Close the original Object once the group has loaded. This will prompt ADUC to redraw the object from the groups window, forcing more properties to appear
Now, go to the Members tab for this group and find the object you’d like to edit. Double-click it and…
[] You’ll never do it the old way again!
Enjoy this workaround! I’ve got no idea why you can’t just edit Attributes directly from Search without these extra steps, but it so much faster than manually browsing to objects that I’d wager you’ll never go back to the old way again.
All credit for finding this work around goes to my colleague and friend Mark Wuerslin for his detective work in discovering this workaround.
Continue Reading...Using ConvertTo-HTML and CSS to create useful web reports from PowerShell
Many times we in Dev/Ops or a sysadmin role will create tools for our own use to get nicely formatted output in the console. Normally projects like this have three phases. In the beginning, people are doing something very manually, or have a huge task to accomplish. In the first phase, it’s good enough to make it work, and get people using it ASAP. From there, it’s a great phase of quickly iterating adding more features and refining the scope of the tool or project, and everyone is happy. Well, everyone but you. The final phase has you putting the finishing touches on everything and really polishing it up. I love on the field engineering, because many times I’m saving someone from a terrible load of work, or making what was arduous a simple task. Drawing put the true potential of powershell and converting others is one of my greatest professional joys.
Now, in this scenario we have a list of computers that need to be migrated from Domain A to Domain B using the Quest migration tools. At the start of the project, we mass imported a list from SCCM of User to Computer correlations into SharePoint, so we use that to track computers and users for migration scheduling. The need here was for a tool that could pull down a list of computers for a particular day, display needed information like the user’s name and also provide a one-stop portal for us to be notified when a computer comes online.
With a nice head-start provided by one of my colleagues, John O’harra, we had a valid pipeline full of objects, which was being used to write out files needed for our import.
Using a few calculated properties, we were set.
Enumerate-SharePoint | Where-Object WorkstationMigrationComplete-ne 'true' | Select-Object `
@{Name="Number";Expression={$global:i;$global:i++}},`
@{Name='User';Expression={$_.AccountName}},`
@{Name='ComputerName';Expression={if
(($_.PrimaryWorkstationName).Length-gt 0){$_.PrimaryWorkstationName}ELSE{"NA"}}},`
@{Name='Location';Expression={$_.Country,$_.State,$_.City}},`
@{Name='Ipv4';Expression={Test-Connection-computername $_.PrimaryWorkstationName -count 1 |
select -ExpandProperty IPV4Address | select -expand IPAddressToString }},`
@{Name='Reachable';Expression={Test-Connection -computername $_.PrimaryWorkstationName -count 1 -quiet}},`
@{Name='2ndComputer';Expression={if (($_.SecondaryWorkstationName).Length -gt 0){$_.SecondaryWorkstationName}ELSE{"NA"}}},`
@{Name='2ndIpv4';Expression={if (($_.SecondaryWorkstationName).Length -gt 0){Test-Connection -computername $_.SecondaryWorkstationName -count 1 |
select -ExpandProperty IPV4Address | select -expand IPAddressToString }ELSE{"NA"}}},`
@{Name='2ndReachable';Expression={if (($_.SecondaryWorkstationName).Length -gt 0){Test-Connection -computername $_.SecondaryWorkstationName -count 1 -quiet}ELSE{"NA"}}} |
Format-Table -auto
Phase 1; Console Only
It works and has a nice utilitarian vibe going on, but it isn’t really something you’d want to put up on the big screen…
It could be so much better! This is a solid phase one tool. It does its job but really no one will be impressed too much. I had to do more!
So I dug into my vast and terrible HTML knowledge and decided to make use of the Tee-Object command to send my pipelined objects out to a Variable instead. Tee is definitely a useful command. Sometimes I’ll use it within a function to output my pipeline to a variable that will persist through a particular phase of a function.
Imaging you had a function that performed a few tasks, Get-Information, Process-Information, and then ActOn-Information. During the Debugging process, you might want to run through the function a few times and then after running, tweak some of your objects to see which properties you have available. Commiting the pipeline objects from each phase to a $global:GetInfoObject, $global:ProcessInfoObject and $global:ActOnInfoObject is a great way to run your tools and then conduct post-mortem on them. In an upcoming blog post, I’ll go more in-depth into this example.
Anyway, once I used Tee-Object, I envisioned running a ConvertTo-HTML command and then allowing the Control Techs to access this file from a share on my PC.
Phase 2; Introduce some sophistication
The first attempt was pretty…meh.
This is what I would define as a phase two offering. It shows a lot of potential and many would say it is good enough to put into production. It is definitely good enough to run on a monitor somewhere, but I knew we could do better. I pulled out a little bit of CSS I love to use, with some alternating table and column rows. I then added a header image (courtesy of a screen print from SharePoint :) and immediately the whole process was elevated to something much more professional looking.
Phase 3; Polish!
Of course, the links are just for appearances, but with a bit of work, it could all be functional. This is where I would call this a phase three deliverable and begin looking for my next project. It can serve well in the field, looking good and getting the job done, and won’t embarrass me later.
The beauty about this whole thing is that all of the heavy lifting is done by the ConvertTo-HTML commandlet and using its parameters.
$HTMLoutput | ConvertTo-Html -title “Migrations for $MigrationGroup“ `
-Head $head
-pre “<img src=’.\header.png’><P>Use this list as a reference for systems which are not currently online.</P>”
-post “<h3>For details, contact Migration Central<br>Created on $date by Stephen Owen</h3>” |
Out-File c:\public\Migration_$MigrationGroup.html
The other bit of the lifting is used in the $header variable, as seen here. Feel free to adapt this to your own purposes and I hope that it helps you get work done quickly using PowerShell.
$head = @" <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Frameset//EN” “http://www.w3.org/TR/html4/frameset.dtd”> <html><head><title>Unmigrated Systems Report</title><meta http-equiv=”refresh” content=”120″ /> <style type=”text/css”> <!– body { font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; }
#report { width: 835px; }
table{ border-collapse: collapse; border: none; font: 10pt Verdana, Geneva, Arial, Helvetica, sans-serif; color: black; margin-bottom: 10px; }
table td{ font-size: 12px; padding-left: 0px; padding-right: 20px; text-align: left; }
table th { font-size: 12px; font-weight: bold; padding-left: 0px; padding-right: 20px; text-align: left; }
h2{ clear: both; font-size: 130%;color:#354B5E; }
h3{ clear: both; font-size: 75%; margin-left: 20px; margin-top: 30px; color:#475F77; }
p{ margin-left: 20px; font-size: 12px; }
table.list{ float: left; }
table.list td:nth-child(1){ font-weight: bold; border-right: 1px grey solid; text-align: right; }
table.list td:nth-child(2){ padding-left: 7px; } table tr:nth-child(even) td:nth-child(even){ background: #BBBBBB; } table tr:nth-child(odd) td:nth-child(odd){ background: #F2F2F2; } table tr:nth-child(even) td:nth-child(odd){ background: #DDDDDD; } table tr:nth-child(odd) td:nth-child(even){ background: #E5E5E5; } div.column { width: 320px; float: left; } div.first{ padding-right: 20px; border-right: 1px grey solid; } div.second{ margin-left: 30px; } table{ margin-left: 20px; } –> </style> </head>
Working out Select-Object with Calculated Properties
Hi all,
I learned of some interesting new abilities of the Select-Object command this week and wanted to share them with you.
For a client demerger operation, we’re using the formerly Quest, now Dell Active Directory Management tools to replicate one AD Domain to another and then merge ACLs of files to ensure a smooth transition from Domain Old to Domain New. One aspect of this task is a bit like herding cats, waiting for users to bring their computers online so that we can trigger the Quest Agent on their computer to rewrite the ACLs across the system, with the other half being behind the scenes ensuring that user inboxes are replicated from Exchange.Old to Exchange.Newness. I wrote this simple tool to help our team track the IP addresses of user machines (as we’re having a DNS issue as well…not our creation but our problem to solve), and whether or not the system is online.
Currently we’re using a SharePoint site to track user and system association, and this process makes use of the ‘Export to Excel’ option. On the next revision, this tool will be able to pull data from SharePoint directly, but I’m not quite there yet.
So, for the purposes of this demo, you’ll need a .CSV file with Username, ComputerName, and the User’s Physical location. It should look something like this.
UserName | ComputerName | Location |
---|---|---|
Lindsey O | bucky | Marietta GA |
Steven A. | NotOnline | Italy |
Paul A. | RaveBoi | Los Angeles |
Nick M | Dallas GA | |
Me | localhost | Marietta GA |
Alright, so our table is made. If you want a sample CSV, use this link. Now, we’re going to make use of an interesting property that the Select-Object command has, in which we can specify a hashtable to define a column heading and expression for each column. You can use this same formatting on Format-List or Format-Table, for what it’s worth. This behavior of using @{Name='ColumnName'; Expression ={#ScriptBlock}}
is also referred to as a Calculated Property.
In our example, we want to first Import-Csv our file with the values. We then pipe it into our Select-Object command, and pull out our ComputerName, UserName, and Location from the values provided. Next, we’ll use the Test-Connection commandlet to test if a computer is online and list if it is Reachable, using the -Quiet parameter to get output in True/False. Finally, if we can ping our machine, we also want its IP address, pulling the IP Address from the Test-Connection command.
$comp \= import-csv .\\Migration.csv
for (;;){
$comp | Select-Object @{Name\='ComputerName';Expression\={$\_.ComputerName}},\` @{Name\='User';Expression\={$\_.UserName}},\` @{Name\='Location';Expression\={$\_.Location}},\` @{Name\='Ipv4';Expression\={Test-Connection \-computername $\_.ComputerName \-count 1 | select \-ExpandProperty IPV4Address | select \-expand IPAddressToString }},\` @{Name\='Reachable';Expression\={Test-Connection \-computername $\_.ComputerName \-count 1 \-quiet}} | Format-Table timeout 90}
If you have a smaller number of computers, you can also define your object explicitly, and skirt the whole Import-CSV, using this useful Syntax.
$comp \= @( \[pscustomobject\]@{name\="Kevin B.";ComputerName\="AMAL-454";Location\="USA"}, \[pscustomobject\]@{name\="Kevin B.";ComputerName\="AMAL-433";Location\="USA"}, \[pscustomobject\]@{name\="Me";ComputerName\="localhost";Location\="USA"})
In either case, the output will be something along these lines.
User ComputerName Location Ipv4 Reachable
---- ------------ -------- ---- ---------
Lindsey O. Bucky Marietta GA 192.168.2.198 True
Steven A NotOnline Italy False
Paul A. DJquazar Los Angeles False
Nick M Akravator Dallas GA False
Me localhost FoxDeployopia 127.0.0.1 True
So, this was quite a quicky, but I hope these techniques help you out. There is a ton of potential for cleverness with Calculated Properties. If you come up with any, feel free to contact me. I’ll share it here with everyone and give you full credit.
Continue Reading...Going on air!
Going on air!
Hi readers, I’m very pleased to announce that the Kitten Mittons are currently scheduled to be featured on the very popular PowerShell Power Scripting podcast, which airs every Wednesday night at 9:30 Eastern Standard Time. If you’ve got a question for the team about our experiences in the Winter Scripting Games, please sign on and ask away in the chat room. Thanks!
Continue Reading...