Question Time: when I want a property, PowerShell gives the whole object!

November 13, 2014 FoxDeploy

I’m posting today on a topic I see over and over again in the forums, on reddit, and have run into myself numerous times. Every person I’ve ever taught PowerShell runs into it too, and most authors have covered this at some point, including Don Jones in ‘The big book of PowerShell Gotchas’.

It always happens, and can take a while to troubleshoot.  The problem boils down to this:

In my Script, for some reason when I call $object.Property within double quotes, PowerShell dumps the whole object with all of its properties! How do I get just one value?

And inevitably this leads to ugly, ugly string concatenation like this:

Write-host ("Operation completed on: " + $object.Property + " at " (Get-Date))

It’s ugly and a bad way to do things. You can end up with strange errors too, when objects of a different type are shoved into one another.

So, even though everyone has had a crack at answering this one, I took my own shot at it.  I’ll show you how you should do this, by merit of explaining it to someone else.

“What’s going on here?”

I’ve been scripting for years in both BASH and Batch but I’m new to Powershell and object-oriented languages. I want to make sure I understand this before moving on with my script. This is the input csv file: FirstName,LastName,ID,Dept,Flag First,Last,5403,Accounting This works:

$inputfile = Import-Csv "\\\\san\\inputfile.csv" ForEach ($user in $inputfile) { If (Get-ADUser -Filter "mobile -eq $($user.ID)") {Echo $user.ID} }

This doesn’t work:

$inputfile = Import-Csv "\\\\san\\inputfile.csv" ForEach ($user in $inputfile) { If (Get-ADUser -Filter {mobile -eq $user.ID}) {Echo $user.ID} } 

What is it about the syntax in the first one that makes it work? From <http://www.reddit.com/r/PowerShell/comments/2lzxgm/new_to_powershell_why_does_this_work_and_this_not/>


 

The Reason Why you’re getting too much; PowerShell just wants to help

Here’s the reason why you’re getting that output. It all has to do with the String! When you put a variable in quotes and in paranthesis, PowerShell will pull out only that single property when evaluating the string. In your first example, you can see this in action, this is what PowerShell is really doing, I’m only going to include the bit on line 3.

ForEach ($user in $inputfile){Write-Host "(Get-ADUser -Filter mobile -eq $($user.ID))"}

(Get-ADUser -Filter mobile -eq 5403)

So, Powershell reads through the line, sees the $variable marker in front of paranthesis, then treats the contents of it as a string. Here, it pulls out only the ID property in that case, because it respects the order of operations. Now compare this to your Example 2, and look at what is happening

ForEach ($user in $inputfile){Write-Host"Get-ADUser -Filter {mobile -eq $user.ID}" }


Get-ADUser -Filter {mobile -eq @{FirstName=First; LastName=Last; ID=5403; Dept=Accounting; Flag=}.ID}

 

See that? PowerShell is reading the characters after the -Filter, and gets to $user and then just dropping in the value for the $user, which includes all of these properties. At the end of the contents of User, it then lamely appends ‘.ID’ to the end.

Nice try, PowerShell, you did your best.

So, the real problem here is that if you want to pull out a single property of an object within full quotes, you need to use $($variable.Property) syntax.


 

Oh, and in case you’re wondering how I did the PowerShell console output in my post? I used an HTML block and figured out using mspaint that the hex color for the PowerShell window is RGB #013686.

<div style="padding: 12px; background-color: #013686; line-height: 1.4;"> <span style="color: #ffffff;"> #YourConsoleOutput here </span> </div>

Results in

#YourConsoleOutputHere

Continue Reading...

The Five Commandments of managing and recovering from a serious outage (with your job!)

November 07, 2014 FoxDeploy

Topic introduction: Consulting 101

I know that I tend to write mostly about PowerShell, tool-building and some sysadmin topics here, but I would like to expand that out and begin writing about the business behind delivering IT and how to be a good sysadmin/consultant. I plan to draw on my experiences serving as an IT Consultant for the last five years.

If you’d like me to touch on a particular topic, or think I’ve made a mistake, please contact me and let me know.

The Five Commandments for recovering (with your job!) from a serious outage or failure

We’ve all had that creeping sensation when we hit enter, and the system takes just a little too long.  Our hands get clammy, we may start to sweat, you get that taste of metal in your mouth.  For instance, when you meant to update one row and see this instead

“Uhm, honey…I might be late for dinner…”

Believe me, I’ve been in this position before, and I survived every instance of it with my skin still on.  When done correctly, you can even build a relationship further through proper management of a serious outage.  First and foremost, when the going gets tough, you should remember the Hitchhiker’s Guidebook cover and…

Thou shalt not panic even if the wall is aflame and spiders are crawling out of the vents

Don’t panic!  Keep your wits about you and understand what went wrong.  Don’t be afraid to immediately inform your technical management that something has gone wrong.   There is no surer method to be shown the door than to try to conceal a problem, especially a serious one.

Put feelers out to your colleagues and peers to seek their feedback in dealing with similar issues.  Perhaps one of them knows a quick method to restore everything. Ensure that you do not cause further damage due to rash decisions.  Once you know what happened…

Thou shalt quench the flames consuming thy infrastructure

Cancel your dinner plans and roll up your sleeves, it’s time to dig in and get things back up and running. If you have the team, appoint a single person as the point man to handle communicating out the status updates, and expect to give updates quite regularly while things are still broken.

If you have the option, aim to get things limping if need be while you engineer a more perfect solution.It’s okay to have an accident, but doing a stupid mistake because you’re tired or under the wire will lead to questions you’d like not to answer.

For an example of a team doing a wonderful job of communicating status updates and really puling together and recover, see how Emory handled progress reporting (https://web.archive.org/web/20140517145618/http://it.emory.edu/windows7-incident/) when they had a damaging run-away ConfigMan task sequence earlier in the year.

Every few hours, they would update a point web page, and they made efforts to roll people off to go home and rest while maintaining the work effort. This is how it’s done, people. Get things up and working and then go home and rest.

When you return to work…

Thou shalt take ownership of thy mistakes and not blame another

I’m really going to emphasize what not to do here. Don’t blame others. Don’t throw yourself under the bus when you do accept the blame either. Finally, don’t be too worried about losing your job, as it takes a lot of money and time to train a replacement. Instead, invest your effort in framing how you’ll explain the problem and really understand what took place. Don’t squirm out of the way by delivering a jargon filled explanation.  Think of how you may feel when the car mechanic comes back with a confusing description of whats wrong with your car, and a huge bill.

In the midst of a disaster is not when you should be updating your resume.

You’ll need to take good notes on what happened and when, you’ll need this because next…

Thou shalt understand the error of thy ways

This means you need to research in great depth the details of what happened.

You need to become an unchallenged expert on the best practices related to the problem, and be able to highlight problems inherent in the previous approach that lead to things falling apart.  Don’t be a weasel about it, as an admin/consultant, we’re here to simplify explanations of things like this to our customers. You’ve got to maintain your credibility, and you can do so with an honest explanation of what went wrong.  You need to write things up. Make it look pretty and identify other similar problems that you can fix while you’re doing this. You’ve got to come up with and present some safe-guards to keep this from happening again. If the same failure occurs again, you’re pretty much going to be shown the door in most places.

It’s of the upmost importance that for the next few weeks…

Thou shalt present thyself in a manner most becoming

It’s time to be on point.  You’ll be under a microscope, as your customers and peers wonder if this was a one-off thing or actually the first indication that maybe you don’t know what you’re doing.

Keep in mind that you need to present yourself as a professional who had an accident of the sort that happens from time to time in any professional industry. You don’t want to be seen as someone in over his head who made a preventable mistake. There are a lot of things you can do at this point to make sure you’re presenting yourself well.

Come into work on time.  Studies show that even in this day and age of universal connectivity and remote work, most managers when surveyed about their workers consistently listed those who came into the office and were there earliest as their perceived hardest workers.

Show up looking sharp. Get your hair cut, look good, and iron your clothes.Avoid flashy colors, as most studies state that men look most professional in charcoal or khaki slacks, and with a light blue or white dress shirt.  Now is the time to speak properly, not in contractions or colloquially, it’s the time to sound like a smart guy too.

Compose yourself.  Stay calm.  You may be the victim of some good natured ribbing over the next few weeks.  Now is not the time to get your back against the wall and lash out at people who are trying to make light of the issue.  Take it all in stride and grin while they throw a little bit of poo at you.  We’ve all been there before.

If you’re in this situation, or recovering from it, let me know if this advice was helpful to you please.

In my next piece in this series, I’ll go through what you should put in a post-mortem or after-action report.

Continue Reading...

Set PowerShell as your CLI of choice in Windows 8. WITH POWERSHELL

November 04, 2014 FoxDeploy

In a conversation on Twitter, I lamented with some friends that Hitting Windows+X in Windows 8 and above opens up the admin window, but still–In 2014–lists Command Prompt as the CLI.

PowerShellWPowerShell Maybe in Windows Vista this would have made sense…but PowerShell had already been out for SIX YEARS when Windows 8 shipped.

With one single line of PowerShell, we can right this grieveous wrong.

 Set-ItemProperty HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced \` -Name "DontUsePowerShellOnWinX" -Value 0 

yoDawg

 

And to test it…

PowerShellWPowerShell1

aaawwwyeah

Continue Reading...

PushBullet + PowerShell = PowerBullet!

November 03, 2014 FoxDeploy

A friend and colleague of mine, Chris Townsend were talking over lunch recently, when he lamented that during a very long scripted process, he would have to manually check back in for status checks to see how this process was going, and might waste a whole weekend in front of the keyboard.  We began trying to think of ways to get notifications if he needed to intervene and manually do something.

We talked about e-mails, but I think it wouldn’t work because of no open SMTP relay.  Then we wondered about sending a text, and I was reminded of PushBullet.  If you’ve never heard of it before, it is a very cool service you can install on your desktop, tablets, phones and even web browsers to recieve and send push notifications.  Your friends can sign up under one single Push list and send each other notifications or cool links.  You can also use it in your scripts, provided you’d like to dig into the SDK and setup your own framework with the API.

Introducing PowerBullet v 1.0

I present to you the (mostly) finished version of my implementation of PushBullet, which I call PowerBullet.  It currently contains only one function, Send-PushMessage, which will send pushes to all of your devices.  In v 2.0, you’ll be able to specify which device a message goes to.  Currently, you can send the following types of messages:

  • Send a Message/ Note (contains a title, and body text) - works
  • Send an address (Will open in the default maps application) - works
  • Send a file which pre-exists on the web - works
  • Send a link (will open as a URL) - works
  • Send a checklist*
  • Upload and send a file*

There are currently issues with sending a Checklist and Uploading a file.  Due to the more complex nature of these tasks, I plan to fully implement them in v2.0.  For now, the code exists and the function will mostly work, but error out.  If you spot the hole in my logic, let me know!

Download PowerBullet here!

To start off, I need to give credit where credit is due:

  • The API Documentation was pretty good!
  • This post on StackOverflow helped me to understand Multipart forms in JSON
  • Finally, I really began to understand how to present credentials using PowerShell because of this post on ElderRec by Jonathan Gray.  I tried to track him down to give him credit, but couldn’t find his real identity.

Getting set up with PowerBullet

  1. First things first, you’ll need to go to PushBullet.com and register.  Sign up for the free service, then check your e-mail to confirm your account.
  2. Go ahead and register some devices too, you could get the client on your phone or install the extension on FireFox or Chrome.  There is also a desktop client too.
  3. Now, you’ll need to make note of your API key Log into PushBullet.  Click your avatar in the upper-right corner, then click Account Settings 01
  4. Copy the API key listed.   This serves as your login to the web service, and all of your registered devices, channels and subscriptions will be accessed using the key.  You’ll also be tracked by PushBullet using this, so if you start pushing 10,000 messages an hour, you can probably expect to receive an e-mail or phone call about your usage.  Don’t give the API key out to people. 02
  5. Paste the key into the $APIKey line within the Send-Pushbullet function and get Pushing!

Some examples

Sending a PushBullet Message if a particular error comes up in the Event Log

 get-winevent -LogName System | Select -first 1500 | ? Id -eq '1074' | % {Send-PushMessage -Title "Reboot detected on System" -msg ("Reboot detected on " + $\_.MachineName + "@ " + $\_.TimeCreated) -Type Message}

03 In this case, look for event 1074, which is a reboot.  This is the Chrome desktop client for PushBullet.

Sending a message containing PowerShell objects

 Send-PushMessage -Type Message -Title "OMG server explode!" -msg "Um, time to come back into the office $Env:COMPUTERNAME died"

04 The $env:ComputerName variable will be automatically swapped for its value. Again in the desktop client.

Send a file which already exists on the web.

Send-PushMessage -FileName "FoxDeploy Logo" -FileType "image/png" -Type File -title "A nice picture" -msg "The FoxDeploy Logo, made by my good friend, Nick Milevsky" -url $url -Verbose VERBOSE: Sending a file VERBOSE: POST https://api.pushbullet.com/v2/pushes with -1-byte payload VERBOSE: received -1-byte response of content type application/json; charset=utf-8 VERBOSE: OK 

Here’s an example from the Android Client.

Sending a link

 PS C:\\temp&gt; Send-PushMessage -Type Link -title "A pretty decent blog" -msg "Some random guys blog" -url http://www.foxdeploy.com -Verbose VERBOSE: Sending a link VERBOSE: POST https://api.pushbullet.com/v2/pushes with -1-byte payload VERBOSE: received -1-byte response of content type application/json; charset=utf-8 VERBOSE: OK

[]06 Showing the results in the Chrome client. Clicking the button takes you to…

Some random guy’s website

Finally, here is an example of embedding PowerBullet within another function. In this case, we’ll make a quick function with a number-indexed hashtable, and invoke Get-Random to get a number. We’ll call this ‘Simulate-DataCenterFault.  If all goes well, this should come up with a random number, then pull the address from the appropriate key-value pair, and then send a PushBullet message with a working address link.

Function Simulate-DataCenterFault {

$random = get-random 4 -Minimum 1

$DataCenterLocations = @{ 1 = "Capitol Lake Park, Olympia, WA 98501"; 2 = "900 Court St NE, Salem, OR 97301"; 3 = "547 L St, Sacramento, CA 95814"; 4 = "1280 Peachtree St NE, Atlanta, GA 30309"}

"Trouble reported at Datacenter $random" ("Address: "+ $DataCenterLocations\[$random\])

Send-PushMessage -Type Address -PlaceName "Datacenter $random" -PlaceAddress $DataCenterLocations\[$random\] -msg "Trouble reported at Datacenter $random" }

Simulate-DataCenterFault 

Continue Reading...

A primer on Docker from the Windows Perspective

October 29, 2014 FoxDeploy

If you’re keeping up with the Azure talks from TechEd Barcelona this week (and you should be!) you’ve heard a lot of mentions about Docker recently.

Wondering what it is?

Docker is a technology that allows an application developer to install and sequence the execution of their application to ‘containerize’ it in a portable container which can be docked and executed anywhere, seamlessly alongside other applications without application installation dependencies causing interference. The key differentiation point here is that the application and its dependencies are virtualized, rather than the underlying OS, as in traditional virtualization. The big benefit to abstraction of the OS is portability and a significant reduction in overhead.

Instead of developers giving out an install script and binaries, they can provide a fully configured Docker image, which can be run on any system with the Docker engine installed, which includes OS X, Windows and pretty much any version of Linux. Keep in mind while running Docker in Windows that while VirtualBox will be used, Docker does not require hardware virtualization support.

This graphic from Docker does a great job of explaining why it is becoming so popular. Note the size difference between a system with many docked containers versus the system load of a system with many VMs.

Traditional VM vs Docker Containers

Early adopters are reporting four to six times increases in density!

I used the word ‘sequencing’ earlier for a reason, as it should be a keyword for anyone who used App-V in the past, evoking either sublime memories of a halcyon era, or a shudder of knowing fear.

Docker can basically be thought of as the second-coming of App-V application virtualization for the Linux World.

Many of the same concepts that we used to sequence applications using that technology apply, such as installing and running an app to declare dependencies and so on. Additionally, these Docker containers can be linked together to facilitate intra-application communication as well.

One should note though that using Docker on a Windows System necessitates the introduction of VirtualBox, as Docker needs OS features from Linux to function. The installation process currently for a Windows system is quite clunky, and involves the install of VirtualBox to run Ubuntu, from within which Dockerized Containers can be used.

This means that if you want to streamline your AWS or Azure experience to cram some containers in along your Windows VMs, you should be mindful of the compute and storage overheads.

Definitely a technology to keep an eye on, especially if it expands to support Windows Applications. Abstracting away the need for the underlying OS is a very powerful concept still in its infancy.

Continue Reading...

Use Invoke-WebRequest to get your physical location

October 23, 2014 FoxDeploy

Hi all,

This is predominantly going to be a script sharing post.   I’ve got a fever for these APIs so expect to see me crank out a bunch of new cmdlettes in the next coming weeks.  I’ve already got one for finding a restaurant in your area using an awesome opentable-scraping API I found on heroku.  Anyway…send me requests, this is soo much fun!

Unlike my previous post, this API is totally free, so you can copy and paste and start using this code today!  Why did I want to do this?  Well in a conversation with a fellow redditor about a way to get Weather Info, he wondered how to do a GPS or geolocation lookup within the script, to have it update as he moved around.

I naturally had to see what I could do!

For this one, it all revolves around using hostIP.Info’s free open API which determines relative user location based on the browser-agent resolved IP address.

This isn’t going to be the most needle-pointed geolocation, but it’s not half bad!   Note that if your users are running on a VPN or Proxy or in a cloud provider, the results for this will be all over the map.

Please correct me!

I’m also pretty sure I’m doing something dumb here.  I had to create this terrible series of Search-String, .Splits and -Joins here to make it work, and I’m certain there is an easier way to get these values that the API returns.  I’ve included a reference in the bottom comment of what an object looks like from this script, so please correct me!  Also, my nested values here breaks the syntax highlighting of WordPress.  Sorry.

Finally, this function is all switch based. That is, it accepts no parameterized input, but relies on Switches instead. I’d nevere seen another script written this way, so if no Switch is provided, it defaults to what I think is the most useful. As I’ve never seen this before, I’m not certain if there is a PowerShell-Best-Way of doing this.

<#
.Synopsis
   Use this Function to perform a lookup on API.HostIP.info which will tell you either the Country, City or GPS Coords
.DESCRIPTION
   Use this Function in your other functions to perform a lookup on API.HostIP.info to obtain the physical location your script is running in
.EXAMPLE
   Get-PhysicalLocation
 
   #Default output is City
   >Atlanta GA
    
.EXAMPLE
   Get-PhysicalLocation -coords | Get-Weather 
 
   #Get-PhysicalLocation will provide Custom Object with a Coords property, which will be cmdlet bound by Get-Weather, which will result in the weather forecast for the local area
   >The weather is generally Clear and currently 57.47 degrees Fahrenheit at Wednesday, October 22, 2014 8:15:08 PM
    wind is gusting up to 6.86 m/PH with a chance of precipitation at 0
 
    The weekly forecast is drizzle on wednesday, with temperatures rising to 79f on monday.
.NOTES
    This function is based on some very ugly regex XML parsing, as I couldn't figure out how to get PowerShell to properly recognize the namespace of the GML XML objects that were being returned.  In a future version, I'd love to resolve this
#>
Function Get-PhysicalLocation {
param ([switch]$Coords,[switch]$City,[switch]$CountryName,[switch]$CountryAbbrev
)
 
#if no switches are specified, convert to $City mode
if (($coords,$City,$CountryName,$CountryAbbrev) -notcontains $True){$City = $True}
 
if ($coords){
 
$coordinates = (((([xml](invoke-webrequest http://api.hostip.info/ | select Content).Content).InnerXml -split ">" | select-string -Pattern "<gml:coordinates" -Context 1) -split "`n")[2] -replace "</gml:coordinates",'').Trim()
[pscustomobject]@{Coords=$coordinates.Split(',')[1],$coordinates.Split(',')[0]}
 
}
 
if ($City) {(((([xml](invoke-webrequest http://api.hostip.info/ | select Content).Content).InnerXml -split ">" | select-string -Pattern "<gml:name" -Context 1)[1] -Split "`n")[2] -replace "</gml:name",'').Trim()}
 
if ($countryName){
(((([xml](invoke-webrequest http://api.hostip.info/ | select Content).Content).InnerXml -split ">" | select-string -Pattern "<countryName" -Context 1) -Split "`n")[2] -replace "</countryName","").Trim()
}
 
if ($countryAbbrev){
(((([xml](invoke-webrequest http://api.hostip.info/ | select Content).Content).InnerXml -split ">" | select-string -Pattern "<countryAbbrev" -Context 1) -Split "`n")[2] -replace "</countryAbbrev","").Trim()
 
}
 
 
<#
Refence of GML object for future version
<?xml version="1.0" encoding="ISO-8859-1" ?>
<HostipLookupResultSet version="1.0.1" xmlns:gml="http://www.opengis.net/gml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noN
amespaceSchemaLocation="http://www.hostip.info/api/hostip-1.0.1.xsd">
 <gml:description>This is the Hostip Lookup Service</gml:description>
 <gml:name>hostip</gml:name>
 <gml:boundedBy>
  <gml:Null>inapplicable</gml:Null>
 </gml:boundedBy>
 <gml:featureMember>
  <Hostip>
   <ip>216.183.126.166</ip>
   <gml:name>Atlanta, GA</gml:name>
   <countryName>UNITED STATES</countryName>
   <countryAbbrev>US</countryAbbrev>
   <!-- Co-ordinates are available as lng,lat -->
   <ipLocation>
    <gml:pointProperty>
     <gml:Point srsName="http://www.opengis.net/gml/srs/epsg.xml#4326">
      <gml:coordinates>-84.4226,33.7629</gml:coordinates>
     </gml:Point>
    </gml:pointProperty>
   </ipLocation>
  </Hostip>
 </gml:featureMember>
</HostipLookupResultSet>
 
 
#>
}
Continue Reading...

Microsoft MVP

Five time Microsoft MVP, and now I work for the mothership


Need Help?

Get help much faster on our new dedicated Subreddit!

depicts a crowd of people in a night club with colored lights and says 'join the foxdeploy subrreddit today'


Blog Series
series_sml_IntroToDsc
series_sml_PowerShellGUI series_sml_IntroToRaspberryPi Programming series_sml_IntroToWindows Remote Management Series The Logo for System Center Configuration Manager is displayed here Depicts a road sign saying 'Learning PowerShell Autocomplete'




Blog Stats