How to Manage Azure from PowerShell on your PC…

2017-07-27T00:01:03+00:00 September 11th, 2013|Uncategorized|

If you use Azure day-to-day like I do…  and you use PowerShell day-to-day like I do…  then it’s time to put them together like chocolate and peanut butter!  What I mean is, let’s use the power of PowerShell to easily manage your Azure services.

I’ll assume that if you’re still reading this, you have an Azure account (if you don’t, you can get a free trial), and you have a Windows 7 or higher PC or server on which to run PowerShell. 

Install the Azure PowerShell modules
Go to the Azure download page, and at the bottom left, download the “Windows Azure PowerShell” bits and install.  Here’s the direct link to the bits, as of this writing.  It’s just a few clicks and a few minutes to let the web-installer do its thing. 

Once Azure PowerShell is installed, hit Start and type PowerShell to see that you now have another option for PowerShell, called “Windows Azure PowerShell”;  click it! 

1-StartAppsAzurePowerShell

Configure the “publishsettings” file

Next we need to link your Azure account with your PowerShell session.  We do this by getting your “publishsettings” file from Azure, and stuffing it into PowerShell.

Run the command: Get-AzurePublishSettingsFile

2-GetFile

…This will launch a browser and you will be prompted to authenticate to Azure (if not already).  You will be prompted for download choices, and you should save file to local folder; something like c:tempAppsAzure that I use in the following example.

Next, we import the settings file with the following command: Import-AzurePublishSettingsFile

3-ImportFile

…of course it depends on what you named the file when you saved it, but this is a standard name format.

Finally, delete the “publishsettings” file — it contains a management certificate file that shouldn’t be left lying around once imported.

4-del

…and that’s about it!  You are now linked to your Azure account and can control your world by command.  Let’s start by taking a look at some of the relevant commands:
get-command *azure*

Mmmm…  Those look like fun commands!

 

Kick the tires

You know, as long as we have an active session, let’s see how I last left my testing lab with a Get-AzureVm command:

5-GetVm

…Hmmm…  It looks like I left my Windows Server 2012 R2 “preview” VM shut off.  Let’s start it up with a Start-AzureVM command, specifying the VM name as well as the Service name:

6-StartVm

Well, that was fun, but now lunch is over and it’s time to shut down the lab “preview” machine again.  But I just want to shut down the VM for later use, not to de-provision the VM and have to re-create it later.  So, I’ll use the Stop-AzureVM command with the -StayProvisioned flag.

7-StopVm

…and so on, and so on.  Now that we’ve got you all set up and have stepped through some basic commands, you should be well on your way to chocolate and peanut butter goodness!

For more detail, make sure to see the Azure PowerShell “Get Started” tutorial:
http://msdn.microsoft.com/en-us/library/windowsazure/jj554332.aspx

And for even more detail, view the Azure PowerShell Cmdlet reference guide:
http://msdn.microsoft.com/en-us/library/jj152841.aspx

Now *you* go have some fun!

 

 

 

PowerShell v4, and Desired State Configuration…

2017-07-27T00:01:03+00:00 August 7th, 2013|Uncategorized|

For me, the most exiting thing to have come out of Microsoft’s TechEd this year is the new PowerShell v4 feature called Desired State Configuration (DSC).  Being able to deploy countless servers, and be assured that they all will have exactly the products you want installed, the way you want them installed, as soon as you want them installed — all with a few lines of scripting code — is priceless.  I know it’s been a couple months now since it was announced, but if you’re anything like me, you’re just really digging in to the Server 2012 R2 features as you get spare time…  and the power of these new features really start to sink in…

If you want to add a server configured like all the rest?  You add a line in an input file.  You want to add a product to hundreds of servers or change a configuration item?  You add a few lines in what is effectively a PowerShell function.  I just can’t help but think how PowerShell has come sooooo far in making a farm of Windows servers as easy as managing a farm of Linux servers has always been the shell and shell tools, or with certain management tools like Puppet and others!  And the Puppet and Chef folks are on board too, as their products start to make best use of these new capabilities.

For all the info you need to get started (if you haven’t already), make sure to check out the TechEd session, “Desired State Configuration in Windows Server 2012 R2 PowerShell”:

…And also catch up on the PowerShell.org blog announcement.  Then, go download the Server 2012 R2 bits and get going!

 😎

 

 

PowerShell – How To Discover and Set Permissions on a Folder…

2017-07-27T00:01:03+00:00 June 12th, 2013|Uncategorized|

I’ve written a few posts here in the past about how to use PowerShell to set NTFS permissions, in a couple different fashions.  But recently I was asked something like, “…okay, I know what permissions I’d like to assign in Windows Explorer, but how do I know what the PowerShell equivalent is?” 

The point of the question is that the description of the permission you see in the GUI is not necessarily what you’d actually put in your PowerShell command when you attempt to apply it.  So how do you know the difference and correlation?

There are tons of references out there for learning more about scripting setting permissions in PowerShell, but it’s not always easy to know *which* permission to set with PowerShell.  So let’s imagine the scenario where we need to add a “custom” permission to a folder via a PowerShell script or command (maybe part of a loop, etc.), and the requesting person has only described to you in the most GUI-like terms what is needed. Step1

In this case, what I usually do is:

1.) Ask the person to set the desired permission on an example folder (if it doesn’t exist already) to be sure that you are talking about the same thing, like this example:

…In this example case we are using the following:

Permission 1: Create File / Write Data
Permission 2: Create Folders / Append Data
Permission 3: List Folder / Read Data
At: Folder name “Bogus”
For: This folder, subfolders, and files
To: LABWorkgroup1

 

2.) Use PowerShell command Get-Acl .Bogus | Format-List to get a readable ACL from the example folder:

 Step2

3.) Now, remove that permission from the folder, and run the above command again to see the difference (or just evaluate the SIDs):

Step3

…and now you can see — among the other permissions — that the above listed permissions translate to LABWorkgroup1 Allow  ReadData, CreateFiles, AppendData, Synchronize; and the Sddl, if you need it: (A;OICI;0x100007;;;S-1-5-21-2087276962-282213542-3505124996-1115)

4.) Finally, set the permission on the new folder:

$folder = "Bogus"
$myGroup = "LABWorkgroup1"
$acl = Get-Acl $folder
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "ReadData", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "CreateFiles", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("$myGroup", "AppendData", "ContainerInherit, ObjectInherit", "None", "Allow")
$acl.AddAccessRule($rule)
Set-Acl $folder $acl

This is a simple example, of course, but it’s an easy way to get it done without chasing down reference documentation.  After a while and frequent use, you begin to kinda’ memorize the various PowerShell permissions options and recognize them — but you can sometimes forget them too, and this is a quick and easy way to figure it out at any time.

😎

 

Powershell – Self-Destruct Button…

2017-07-27T00:01:03+00:00 May 29th, 2013|Uncategorized|

While it usually is the case that the owner or creator of a tool or device would like to keep the item he or she has created safe and sound, occasionally one might create a one-time-use tool that is designed to service its purpose for only a brief time, and then be eliminated — in case further use of the tool is harmful to the purpose for which it was originally invented.  Imagine a wrecking ball for instance; while extremely useful during demolition phase, you don’t want it lying about swinging the big iron ball near your new glass windows when construction is nearly completed, do you?

In these cases, I am reminded of Dr. Heinz Doofenshmirtz, the famous inventor.  For those that know me, it will likely come as no surprise that I’m a big fan of the Doctor’s prolific and voluminous work.  One interesting (and perhaps little-known) facet of his work is that each of his inventions holds an essential – but often overlooked – element of self-mitigation.  It has been said that this feature was sometimes erroneously invoked before the completion of its ascribed task, but — and possibly due to the nature of the feature — scant evidence of this is available.  Nonetheless, he was diligent in making sure that the feature was always available, so none of his tools could cause harm beyond its intended usage.

So it is in this vein — and in honor (and in the spirit) of Dr. Doofenshmirtz — that today I’ve written what might perhaps be one of the more intriguing and perhaps jocular scripts yet:  A PowerShell Self-Destruct Button. 

This is a script that prompts you whether or not it should self-destruct; and then if so, promptly deletes itself.  Enjoy:

 

$CurrentScriptFullPathName = $MyInvocation.MyCommand.Definition
$CurrentScriptName = $MyInvocation.MyCommand.Name
clear
write ""
write "Self-Destruct option: "
$SelfDestructChoice = Read-Host "Do you wish for this script ($CurrentScriptName) to destroy itself upon completion? (Enter Yes or No)"
if ("$SelfDestructChoice" -eq "No")
{
  write ""
  write "Okay, this script will not Self-Destruct."
  write "Keeping: $CurrentScriptFullPathName"
  write ""
}
elseif ("$SelfDestructChoice" -eq "Yes")
{
  write ""
  write "You pushed the Self-Destruct button! This script will now attempt to delete itself..." 
  #write ""
  write "Deleting: $CurrentScriptFullPathName"
  Remove-Item $CurrentScriptFullPathName
  Start-Sleep 3
  write ""
  write "Validating removal...  Is $CurrentScriptName still present?"
  Start-Sleep 3
  Test-Path $CurrentScriptFullPathName
  write ""
  Start-Sleep 3
}
else
{
  write ""
  write "Invalid OverRide choice: "$SelfDestructChoice" is not valid.  Must be Yes or No. Exiting!"
  write ""
  exit
}
write "Complete! Exiting..."
Start-Sleep 3

To walk through this script a bit:  During processing, it first gathers up PathName and ScriptName variable values to help it understand where it is and what it might delete (you don’t want to delete the wrong file!).  Then, it asks you the deadly-serious question of whether or not it should be deleted upon completion.  If not, exit.  If so, self-destruct/delete (and validate).  All that, and a few formatting items to make it all nice.

There you go!  You can copy the text into a file, run it, and amaze your friends.  Maybe amaze the entire Tri-State Area!

🙂

 

Powershell – Check for PS version and act accordingly…

2013-05-22T22:29:39+00:00 May 22nd, 2013|Uncategorized|

In recent posts, we’ve been outlining some important day-to-day differences in PowerShell CMDlets and features between v2 and v3.  And right now I’m working with a customer that is in the midst of transitioning between XP and Win7, and between Server 2003 and 2008/2012, where these differences really start to matter performance-wise. 

So, we’ve got lots of PowerShell tools we wrote in v2 that we are slowly getting around to updating to the new features in v3.  But the thing is, we still can’t be certain where these scripts will be run, and by whom.  So we’ve put together a little “version detector” to help run the correct version of the command and give the best performance possible, whenever possible.  And as a result, you — the reader — can apply this type of thing to any script that might be run in a mixed environment.

This example below features the new -Directory flag in the PowerShell v3 Get-ChildItem, though you could just as easily replace that line in each section with any other CMDlet that behaves differently between versions.  Just modify this section, and wrap it around your CMDlet with the updated v3 capability…

 

$hostVersionInfo = (get-host).Version.Major
if ( $hostVersionInfo -eq "2" )
{
  # For PowerShell v2
  write "We appear to be using PS version $hostVersionInfo... That's okay, but this script processes faster with PS v3!"
  write ""
  $containers = Get-ChildItem -path $MoLoPath$CurrentParent -recurse | ? {$_.psIscontainer -eq $true}
}
elseif ( $hostVersionInfo -eq "3" )
{
  # For PowerShell v3
  write "We appear to be using PS version $hostVersionInfo... Good!"
  write ""
  $containers = Get-ChildItem -Directory -path $MoLoPath -recurse
}
else
{ 
  write-host "Unknown/unapproved version of PowerShell. Exiting!"
  exit
}

 

Normally, I’d explain some of the functionality in the script; but it’s fairly simple, well-commented, and in general pretty descriptive.  It just detects which version of PowerShell you’re running, and runs one of the two version of the CMDlet.  So you should be able to figure it out quickly even if you’re new to this stuff. 

Of course, if you have a question (or have a better way of getting it done), feel free to comment. 

So that’s it, I hope it helps!

🙂

 

 

Powershell – Interactive Ping Test…

2013-05-15T22:39:09+00:00 May 15th, 2013|Uncategorized|

Here’s a fun, goofy little PowerShell script for you. 

Last week Matt and I were working on a “Go-Live” event — where every moment is part of a timed, scripted series of steps — and one of Matt’s critical remote workstations crashed.  Matt had to move on to other tasks while waiting for the machine to come back up, but in that waning moment we wondered to each other… “In all the PowerShell scripts and tools we’ve written, how is it that we never wrote a ‘Host Up’ notification script?”

Well, we can’t let that stand.  So we began to devise the scripts in our heads, and later that evening I scratched it down so that we’d have it next time. 

 

$MyRemoteHost = "8.8.8.8"
$MyFlag = "False"
while ($MyFlag -eq "False")
{
  $MyResult = ping -n 1 $MyRemoteHost |findstr /C:"Reply "
  if ($MyResult -ne $null)
  {
    #write "$MyRemoteHost is up!"
    #Or do something cool here...
    $LoadStatement = [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
    $MyInput = [System.Windows.Forms.MessageBox]::Show("$MyRemoteHost is up.  Do you want to EXIT?","Yuuup!","YesNo","Warning")
    if ($MyInput -eq "YES")
    {
      break
    }
  }
  Start-Sleep 5
}

…why?  Just because we can.

😉

 

 

Powershell – How recursive directory searches got better with PSv3…

2017-07-27T00:01:04+00:00 April 17th, 2013|Uncategorized|

In the old days, we ate dirt for dinner, brushed our teeth with sticks, used PowerShell v2 — and we *liked* it! 

There, that’s my tribute to Dana Carvey as “Grumpy Old Man”.  Google it, kids.

Anyway, I’ve got an absolute ton of old PowerShell scriptlets that I have lying about that I regularly cannibalize or resuscitate back into production.  And since we are in that squishy transitional period between PowerShell v2 and v3, I don’t always bother to check them for compatibility with v3 or update features in the script to take advantage of new capabilities.  But I hit on one v3 improvement the other day that solved a problem has bugged me so much for so long that I wanted to shout from the mountaintops about it!  And since I live in mostly-mountainless Michigan, the blog is the best I can do…

Really it’s such a little thing.  But it’s so overdue.

In the past, if you wanted to recursively inspect a folder structure on a remote server — for instance while fishing for explicit NTFS permissions on folders — you were forced to inspect all folders *and* files, no matter if you only wanted folders.  Basically, you had to ask for everything (all children folders and files, recursively), then parse the result to extract the folders (check psIsContainer) from the listing.  Here’s an example of this, similar to what you might see all around the internet:

# For PowerShell v2
$containers = Get-ChildItem -path $TopPath$CurrentParent -recurse | ? {$_.psIscontainer -eq $true}

 Of course, this could be incredibly wasteful in processing, network bandwidth, time, etc…   All this time I’ve always wished there was a way in my loops to just ask for ONLY the folders, to save all of that waste.  Thankfully, this has arrived with v3.  Behold:

# For PowerShell v3
$containers = Get-ChildItem -Directory -path $TopPath$CurrentParent -recurse

 This has significantly sped up some of my analysis scripts that I run in a large enterprise, cutting as much as half a day off of some of my execution times (I did mention it was large).  So really what this means is that I have to start spending more spare time looking through the v2/v3 differences…  But I won’t have any spare time until I implement more v3 changes…  Quite a conundrum… 

😉

 

Powershell – Query Active Directory for Server Versions…

2013-03-20T22:45:57+00:00 March 20th, 2013|Uncategorized|

Today, I’m writing about a simple-but-useful command that just might help you get a better understanding of the quantity and variety of Windows servers you have in your environment, with just a few caveats.  The most accurate way to get such information, of course, is to query Active Directory in real-time to get the most current information possible.  And the easiest way to do that (in my opinion), is to use PowerShell.  So launch a console and let’s get to it…

But first, if you haven’t launched the pre-loaded Active-Directory PowerShell Module, then let’s do that now:

Import-Module ActiveDirectory

Here’s a first blush at how we can list all AD-based computers, grabbing only the interesting properties we need, formatting the output to a list, and redirecting the results to file (I’ve seen some things like this while ‘Googling):

Get-AdComputer -Filter * -Properties IPv4Address,OperatingSystem,OperatingSystemServicePack | Format-List Name, IPv4Address, OperatingSystem* > OutputServerList.txt

Now, let’s dig deeper, and perhaps refine the command a bit.  First, the filter is a wildcard, and retrieves all computers.  That might be fine in a small environment with few computers; but we’re really only after Servers here, and we might be working in a larger environment.  So, we will change the filter to use an LDAPFilter and get a bit more granular like this:

-LDAPFilter "(OperatingSystem=*Server*)"

Next, I think the results will actually look better if we output them to a CSV, so we’ll drop the redirect and list formatting, and replace it with a pipe like this:

| Export-Csv ExportCsvServerList.csv

Now a warning about the CSV export…  Unfortunately, Microsoft chose to include a “restricted” symbol (little r in a circle) in the Server 2008 (non-R2) name, like this:

Windows Server® 2008 Standard

…and, the CSV export operates only with the ASCII set by default.  Sheesh.  So, we use the UTF8 flag to make sure the wacky “restricted” mark is rendered correctly, like this:

| Export-Csv -Encoding UTF8 ExportCsvServerList.csv

So with all that, we end up with a command looking like this:

Get-AdComputer -LDAPFilter "(OperatingSystem=*Server*)" -Properties IPv4Address,OperatingSystem,OperatingSystemServicePack,OperatingSystemVersion | Export-Csv -Encoding UTF8 ExportCsvServerList.csv

And since it’s a spreadsheet you can further filter/format/manipulate the results how you see fit.

One more thing that causes confusion sometimes: 

Be aware that even though we are calling ActiveDirectory for these servers and their correlating properties, there’s one of these items that don’t come from there: the IP Address.  As you are likely aware, the IP address of a computer object is not stored in the directory; so what is actually happening is that the Get-AdComputer module is retrieving the FQDN of the computer, and doing a DNS query to resolve it to the address for you. 

Now, this can be good or bad, depending on your situation; for instance, it might slow down your 8000+ server export… or might also help alleviate the burden on your AD server as you make the query (while it delays the processing a tad to retrieve the name).  Also, you’d better be able to rely on your DNS to return valid values, or the results might be confusing/misleading! 

I hope that helps…  Thanks for reading, and by all means if you have additional tips, be sure to comment!

 

 

 

PowerShell – Detect Group Membership Type…

2017-07-27T00:01:04+00:00 March 6th, 2013|Uncategorized|

It should come as no surprise that adherence to naming conventions and good Active Directory (AD) Organizational Unit (OU) structure are things that can make an Enterprise Administrator’s life much easier. 

Take, for example, the situation of having a naming convention for group objects in AD that dictates a single-letter suffix of either a “C” (to indicate a group of computer objects) or a “U” (for a group of user objects).  In this case, a group might be named something like, “Detroit Application Data U”, or “Chicago Printers Floor2 C”.  And with intentions such as these — and human beings being what they are — it’s inevitable that some users will end up in computer groups, and vice versa.

So how to we check for this messiness?  With PowerShell, of course…

We create a script that will accept an array of our AD OUs (or group-specific OUs if you’re lucky), loop through them, grab all the groups and the memberships, and do a validation to make sure the members are of the correct class (note that I could fill up pages of the lines of code for this, depending on your specifics; so I’ll just stick with the main conceptual points).  Let’s dive into the code snippets!

First, add your OUs into an array, and other variables.  Of course, you might not be able to just scrape a level with PowerShell and grab all your OUs…  Oh, but you *do* have a perfectly-regulated AD hierarchy, don’t you?  Whether it’s perfect or not, AD structure goes a long way here; and my examples show how convenient it is if you have all your groups in a standard ou=GROUPS structure or some predictable way.

$OUs = @("Detroit", "Chicago", "Los Angeles")
$MyDomain = "dc=MyDomain,dc=org"

Then you start to loop and grab all the groups in an OU:

foreach ($OU in $OUs)
{
  #... skipped a few more lines of code here...
# Here we get the list of our groups for the loop
$OuGroupNames = Get-ADObject -Filter {(ObjectClass -eq "group") -and ((name -like "* U") -or (name -like "* C"))} -SearchBase "ou=Groups,ou=$OU,$MyDomain"

And, now that you have the groups, you can start to evaluate each group like this:

  foreach ($OuGroup in $OuGroupNames)
  {
    #...skip more code.. What are we skipping here? Oh, validations, error-checking, and stuff...
# we need the group name and DN    $OuGroupName = $OuGroup.Name     $OuGroupDn = $OuGroup.DistinguishedName

Now, we can truly check the object membership type!

    # If it is a user group...
if ($OuGroupName -like "* U")     {       $MemberList = Get-ADGroupMember -Identity "$OuGroupName"
# ...it had better be a user...       if ($Member.ObjectClass -like "computer")
{
#...or we kick out an error to the report!

And so on.  Of course, you’d do the converse of the snippet above for a user-type object in a “C” group.  By the way, this can lead to all kinds of other error detection too; in fact, the main reason I couldn’t show all my code is that I ended up adding checks for empty groups, groups with members from external OUs, and so on.  Because basically, once you have the group attributes and its membership list in hand, you may as well do some validation while you’re there…

So have fun with it, and see where it leads you…  And make sure to drop me a line if you need any help putting the whole thing together.

🙂

 

 

 

 

AD Attributes – LastLogon vs. LastLogonTimeStamp…

2017-07-27T00:01:04+00:00 February 27th, 2013|Uncategorized|

A little while back I was working at an enterprise that has many locations across the United States.  I had a list of 30 usernames (from one specific out-of-state location) and a couple brand-new test accounts that I wanted to report on their “last logon times” from the Active Directory domain.  I put together a quick PowerShell script to loop through each user and report on the “lastLogon” time and I had (what I thought were) my results in no-time.  Here is a snippet of the code:

Get-ADUser $UserNameToSearch | Get-ADObject -Properties lastLogon

First, I opened up an RDP session to a domain workstation that I had access to at the out-of-state location that I was working with at the time and I went ahead and logged in with my test user.  I waited a few minutes for the replication to occur back to my location’s domain controller and then I ran the script from my local workstation.  Surprisingly, there were no results reported for that test account, but there were current up-to-date results for 95% of the users who were on my list that are said to work at that same location.

So I logged out, logged back in, waited, and ran the script again.  Still, no “logon time” results for my test user account.

Very interesting….

I did a few minutes of research on the “lastLogon” attribute and then I discovered I was searching the wrong attribute, per Microsoft’s MSDN Attribute Library which states: “This attribute is not replicated and is maintained separately on each domain controller in the domain. To get an accurate value for the user’s last logon in the domain, the Last-Logon attribute for the user must be retrieved from every domain controller in the domain. The largest value that is retrieved is the true last logon time for that user.  But since the enterprise I was working with had more domain controllers than I could count on one hand so I chose to find a simple alternative.

After a few more minutes of research I then found the attribute that is replicated across all domain controllers, the “lastLogonTimeStamp” attribute.  I updated my script to:

Get-ADUser $UserNameToSearch | Get-ADObject -Properties lastLogonTimeStamp

I then had the results that I expected and I carried on with my day.

Hopefully this experience will save you time and effort!

 

 

 

Load More Posts