Quantcast
Channel: Scripting Blog
Viewing all 2129 articles
Browse latest View live

PowerTip: Remove User from Lync Server 2013 with PowerShell

$
0
0

Summary: Learn how to use -whatif to safely remove a user from Lync Server 2013.

Hey, Scripting Guy! Question I need to remove users from Lync by using PowerShell, but I'm a bit nervous.
          Is there some kind of built-in test mode in Lync?

Hey, Scripting Guy! Answer Use the -whatif parameter when you disable the user to show what will happen
          without actually changing the system, for example:

Disable-CSUser –identity 'Zaphod Beeblebrox' –whatif


Managing Lync Server 2013 with Windows PowerShell—Part 4

$
0
0

Summary: Have a rollback plan for disabling a user in Lync.

Hey, Scripting Guy! Question Hey, Scripting Guy! Before I shut down all of these Lync accounts on our environment, my boss would like to see what my rollback plan is. Other than restoring from backup, is there a quicker "undo" I can leverage by using Windows PowerShell?

—LN

Hey, Scripting Guy! Answer Hello again LN!

Honorary Scripting Guy, Sean Kearney, is here to show you how Windows PowerShell can give you a rollback in Lync (well sort of)!

     Note This is the fourth part in a series. You might also enjoy reading:

One of the interesting things I had to deal with on my last job was implementing a rollback plan—as many IT professionals do. It didn't matter if we are touching an attribute, powering down a dead Hyper-V box, or rolling out a new cluster. We have to plan for when things go bad.

In the case of disabling users in Lync, you are dealing with a system that isn't just a simple chat window (although it does get used for that a lot too). You're dealing with collaboration, front-facing client meetings, and telephony.

Interfering with any of these could find a job change from working in IT to suddenly and permanently working with the co-op students. Due to our last session, apparently the co-op students don't even have Lync, so it would be a pretty boring job.

So before we do anything that might cause problems, we want a rollback plan—something other than, "I'm going to restore the SQL Server database for Lync." To me, that sounds a little closer to "disaster recovery" than rollback.

We can get a lot of this information by using the Get-CSUser cmdlet and storing it away as an XML file.

If you run Get-CSUser on Mr. Arthur Dent, we can visually see most of his settings:

GET-CSUser –identity 'Arthur Dent'

Image of command output

If we were to export this information as an XML file, we could access it later, even if the original object was no longer in Lync:

GET-CSUser –identity 'Arthur Dent' | EXPORT-CliXml HavingAVeryBadDay.xml

So if we captured Mr. Dent's information and then oh-so-casually deleted him from Lync like this:

DISABLE-CSUser –identity 'Arthur Dent'

...we could immediately re-create him in Lync with this captured information:

$CSUser=IMPORT-CLIXML HavingAVeryBadDay.xml

The Windows PowerShell object $CSUser will now have the equivalent to a photocopy of Mr. Dent's informaiont before we scrubbed him from Lync existence.  With this information, we can rebuild Mr. Dent better, faster, and stronger than before...the 6-million dollar towel man!

First we identify the properties that we need to start. In our case, we only need to trap for the very details we used to create the user initially:

  • Identity
  • RegistrarPool

We don't actually have to trap for the SIP address type because we already have the full SIP address. We can grab that from the $CSUser object we just imported:

$Identity=$CSUser.DisplayName

$RegistrarPool=$CSUser.RegistrarPool.FriendlyName

$SIPAddress=$CSuser.SipAddress

Now to recreate the user we can just re-run the ENABLE-CSuser Cmdlet in this format

ENABLE-CSUser –identity $Identity –RegistrarPool $RegistrarPool –SIPAddress $SIPAddress

Are we done? Of course not.

This simply creates a new Lync user who can sign in. We have to add some additional things to trap for. In our environment, which is quite simple, we only need to trap if the user's Lync address was previously disabled:

SET-CSUser –identity $Identity –Enabled $CSuser.enabled

To prevent a disaster, we could capture all of the data before removing the users. In the case of our poor, hapless, Lyncless co-op students, we would have previously run this:

Get-Aduser –filter * -searchbase 'CN=CoopStudents,CN=Staff,DC=Contoso,DC=Local' | Foreach { GET-CSUser –identity $_.Name } | EXPORT-CLIXML Rollback.xml

Then as part of our rollback, we could do an Import-CLIXML like this:

$Rollbackinfo=IMPORT-CLIXML Rollback.xml

Then step through the information and re-enable the users with their previous status:

$Rollbackinfo | Foreach {

$CSUser=$_

$Identity=$CSUser.DisplayName

$RegistrarPool=$CSUser.RegistrarPool.FriendlyName

$SIPAddress=$CSUser.SipAddress

ENABLE-CSUser –identity $Identity –RegistrarPool $RegistrarPool –SIPAddress $SIPAddress

SET-CSUser –identity $Identity –Enabled $CSuser.enabled

}

In a larger environment (for example, one with Telephony enabled and different features controlled per user), you would write your rollback script to parse through this object on a more detailed level. But the process is almost identical!

Pop back in tomorrow and we'll finish up some basic management tasks. Then on the weekend, we'll discuss how to automate a little of the backup of this environment!

I invite you to follow The Scripting Guys on Twitter and Facebook. If you have any questions, send an email to The Scripting Guys at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then remember to eat your cmdlets each and every day with a dash of creativity.

Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy

PowerTip: Get List of Blocked Domains on Lync with PowerShell

$
0
0

Summary: Use Windows PowerShell to get a list of all domains that are blocked from federating with Lync.

Hey, Scripting Guy! Question I am auditing a client's Lync server and need to pull up a list of all the Domains that are presently blocked or not blocked with Lync. How can I easily do that with PowerShell?

Hey, Scripting Guy! Answer Run the Get-CSBlockedDomain cmdlet:

GET-CSBlockedDomain

If you'd like to export that information, pipe it to Export-CSV:

GET-CSBlockedDomain | EXPORT-CSV BlockedList.csv

Managing Lync Server 2013 with Windows PowerShell—Part 5

$
0
0

Summary: Learn about basic Lync auditing.

Hey, Scripting Guy! Question Hey, Scripting Guy!

I go sites and need to work on various Lync servers. Often my first challenge is getting their configuration. Where do I start?

—RD

Hey, Scripting Guy! Answer Hello RD,

Honorary Scripting Guy, Sean Kearney, is here to help you out with a little basic Lync auditing.

     Note This is the fifth part in a series. You might also enjoy reading:

Now my good friend, Lync MVP, Pat Richard, is probably nodding on this one. The first place you go to get your Lync configuration is (do not stop, do pass Go…. MOVE IT, MOVE IT, MOVE IT!) the Lync Server Topology Builder!

This is one of the key applications in Lync for creating and editing the topology, but you can also use it to get a copy of it! You will see this window when you start up:

Image of menu

So download an existing Topology if you have the permissions. This will gather the infrastructure of all configurations, Lync servers, voice gateways, and even your Lync Edge Server setup.

Now if you don't have access, but the client has handily stored the file, you can open the file instead. This is faster, but it may not be as current.

Image of menu

When you are done, you can save that file anywhere, including on a portable USB key (as opposed to the large, oversized, novelty, 1987 Mercedes 300 SDL shaped kind).

You can re-open this file offsite if you need to spend more time examining a configuration or (if you're really good) building a test environment to determine why a site might be acting funky.

Of course, the one server that it won't have information about is your IIS Application Request Routing (ARR) or any server doing the special FQDN name translation for your inbound connection. That server won't show up because sometimes it can be substituted by a good name translation rule in a router. So technically, although it might be a part of your Lync topology, it doesn't actually have Lync services on it. That is one you'll need to ask about if you're auditing.

You can also go in to Windows PowerShell and start asking sooooo many more questions of Lync—if you're curious—and what IT professional isn't?

Would you like a quick and dirty breakdown of your Lync sites? Run the Get-CSSite cmdlet:

Image of command output

Would you like to see the cmdlets that various security groups have access to in Lync? Lync lives in the world of role-based access control (RBAC ). So within Lync, certain Active Directory security groups have access to certain cmdlets.

You can easily find out by running the Get-CSAdminRole cmdlet. But the output is a bit much. We'll clean it up so you get a useful list instead:

GET-CSAdminRole | Select-object Cmdlets, Identity

Image of command output

From here, I can see the various cmdlets assigned to Active Directory groups like CS-Administrator. If you dig about, you'll see there are even cmdlets to tweak those lists to meet your needs in your organization!

Image of command output

You can even have Lync tell you all of the users who have Enterprise Voice (the ability to use Telephony, make phone calls from Lync, or in some cases, have an actual Lync handset on their desk). One cmdlet folks! One cmdlet!

GET-CSUser | Where { $_.EnterpriseVoiceEnabled }

Or get everybody who doesn't have it:

GET-CSUser | Where { $_.EnterpriseVoiceEnabled –eq $FALSE }

In fact, the various amounts of information you can pull from Lync via Windows PowerShell is dizzying! Take a look at the massive pile of only Get cmdlets in Lync:

Image of command output

So if you're a new Admin to Lync, I'm hoping this week has been helpful to get you comfortable with some basic management in Windows PowerShell. If you're a Lync MVP like my good friend, Pat Richard, and would like to share, please add to the comments section. It's community that makes Windows PowerShell great!

…and that's people like you!

Stop by tomorrow and we'll discuss some things that you need to back up that Lync infrastructure and make your life a little smoother. I promise to make it quick. After all, it is the weekend!

I invite you to follow The Scripting Guys on Twitter and Facebook. If you have any questions, send an email to The Scripting Guys at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then remember to eat your cmdlets each and every day with a dash of creativity.

Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy

PowerTip: List All Lync Enterprise Voice Users with PowerShell

$
0
0

Summary: Get a list of users and phone numbers from your Lync infrastructure.

Hey, Scripting Guy! Question How can I use Windows PowerShell to pull a weekly list of all our Lync Telephone numbers?

Hey, Scripting Guy! Answer Use the Get-CSUser cmdlet, and in your Lync Server management shell, type:

GET-CSUser | Where { $_.EnterpriseVoiceEnabled }

If you'd like a list of only the names and phone numbers, use:

GET-CSUser | Where { $_.EnterpriseVoiceEnabled } | Select-Object DisplayName,LineURI

Weekend Scripter: Basic Lync Server 2013 Backup and Restore—Part 1

$
0
0

Summary: Learn how to make a rudimentary backup for a simple Lync Server environment.

Honorary Scripting Guy, Sean Kearney, is here. Today we're going to play a game of "Let's Pretend."

Let's pretend you got hired in a new company or are taking over from someone who had to deploy a simple Lync infrastructure. This will be a bit more complex than last week when we talked about simple management techniques for Lync Server 2013. Be sure to read this series of Hey, Scripting Guy! Blog posts: Managing Lync Server 2013 with Windows PowerShell.

This time, our configuration will be:

  • Lync Server 2013 Standard as a front edge
  • Lync Server 2013 Standard in an edge configuration
  • A server running IIS for Application Request Routing (ARR)
  • Servers are virtualized

So the question is, "How do you want to back up this puppy?"

The magic answer is (of course as always in the IT community), "It depends."

  • How much space do you have available for backup?
  • What's your available software?
  • What is the acceptable downtime?

And the list can go on and on—like any server.

Before we go any further, I'm going to point you to Backing Up and Restoring Lync Server 2013. This topic discusses all the ins and outs of backing up your Lync environment.

From a simple standpoint, you could back up the virtual machine as a whole—the entire file structure in one complete swoop. All three machines!

Is that a good approach? I can say from personal experience that it does work and it requires very little effort to restore. It does, however, require time. And the bigger those servers are, the more time it will take to restore them. It also takes more space (you're going to have to put all that data somewhere).

So let's go with a smarter approach. Let's find out what the server actually needs to have restored. (There's a concept.)

Let's assume that last weekend we took care of most of the prerequisites for creating a Lync server. The Lync infrastructure was hauled off by Zaphod Beeblebrox in the Heart of Gold. It seems improbable, which is most likely why it happened.

Now we have a disaster recovery scenario. We could plug together most of the prerequisites we created last week as part of a disaster recovery Windows PowerShell script. But think about it. If you were to leverage SCCM, MDT, or any approach for spinning up a new machine with ease, and simply spin up a fresh Lync server afterwards, what's missing?

All together now class: THE CONFIGURATION.

So the first part (as we read about in Backing Up and Restoring Lync Server 2013) lives in the wonderful world of Windows PowerShell. (What do you mean you didn't read the documentation? No soup for you!)

So we'll need our Lync topology—the very file that defines our Lync infrastructure. We can retrieve this by using the Export-CSConfiguration cmdlet. (We'll presume that in all of the following examples, you're storing the files in a folder called C:\Backup, and we're running it on the Lync server.)

Export-CSConfiguration –filename C:\Backup\Topology.zip

This will create a simple ZIP file that contains your Lync Server 2013 topology.

Then we'll grab information from the Central Management store. One cmdlet again. Export-CSLisConfiguration will save the day:

Export-CSLisConfiguration –filename C:\Backup\CentralMgmtStore.zip

This creates a simple ZIP file that contains the information from your Central Management store.

In our case, we are running a single front-end server, so we need to run the following cmdlet only once. This backs up all the user data from the SQL Server database on that front-end server:

Export-CsUserData -PoolFQDN eot-lync.contoso.local -FileName C:\Backup\EOT-Lync.zip

In addition, we should make sure that our SSL certificate file is backed up. Yes! We can do that with Windows PowerShell:

GET-ChildItem CERT:\localmachine\my | where { $_.HasPrivateKey } | Foreach-Object { [system.IO.file]::WriteAllBytes("C:\Backup\$($_.thumbprint).pfx", ($_.Export('PFX', ‘secret’)) ) }

So for our Lync server, we could have a single Windows PowerShell script to get the bulk of the information for the backup like this:

Export-CSConfiguration –filename C:\Backup\Topology.zip

Export-CSLisConfiguration –filename C:\Backup\CentralMgmtStore.zip

Export-CsUserData -PoolFQDN eot-lync.contoso.local -FileName C:\Backup\EOT-Lync.zip

GET-ChildItem CERT:\localmachine\my | where { $_.HasPrivateKey } | Foreach-Object { [system.IO.file]::WriteAllBytes("C:\Backup\$($_.thumbprint).pfx", ($_.Export('PFX', ‘secret’)) ) }

Then the only thing that we need do is back up the file stores (which are in a single shared folder on your Lync server).

Do you see something nice going on here? It means that stock out-of-the-box, we don't need an expensive agent to back up Lync Server. We can simply leverage a standard file server agent (versus using a SQL Server backup). It doesn't negate that option. The more ways you have to back up, the merrier. But it does mean that with a little Windows PowerShell, you can get all the data you need in one shot!

Pop in tomorrow and we'll look and what is need to back up the IIS server that is running the ARR, then we can all sit back and enjoy a round of Pan Galactic Gargle Blasters!

I invite you to follow the Scripting Guys on Twitter and Facebook. If you have any questions, send an email to the Scripting Guys at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then just remember, the Power of Shell is in You.

Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy 

PowerTip: Export Lync Topology with PowerShell

$
0
0

Summary: Use the Lync cmdlets to obtain a copy of the Lync topology.

Hey, Scripting Guy! Question Instead of going through the GUI wizard, can I use Windows PowerShell to schedule a fresh copy
          of my Lync topology as a regular nightly task so I can compare deltas?

Hey, Scripting Guy! Answer Run the following Windows PowerShell cmdlet to create a file called Topology.zip with all of your topology:

Export-CsConfiguration -FileName C:\Backup\Config.zip

Weekend Scripter: Basic Lync Server 2013 Backup and Restore—Part 2

$
0
0

Summary: Use native automation and Windows PowerShell cmdlets to back up Lync Server 2013.

Honorary Scripting Guy, Sean Kearney, is here to finish up my crazy weekend fun automating Lync backup.

So we've already gone through probably the trickiest part, which is getting the bulk of the Lync server infrastructure backed up. To read about that, see Basic Lync Server 2013 Backup and Restore—Part 1.

Now what else could be backed up? How about the firewall settings?

Obtaining the firewall configuration of your servers is incredibly easy within Windows Server 2012 R2. One single cmdlet gets us everything:

Get-NetFirewallRule –enabled True

If we'd like to grab a copy of the rules, we could store each within an XML file, and maybe even name the file based on the server name:

$Name=(Hostname)+'-FirewallConfig.xml'; Get-NetFirewallRule –enabled True | Export-CLIXML $Name

Running this on each Lync server would give us the present inbound and outbound firewall rules as a single file that we could back up.

Believe it or not, we've already backed up the edge server. How did that happen? The edge server configuration (independent of firewall settings and certificates) simply relies on the topology XML file for defining its configuration.

Now on to our IIS server, which is performing the role of Application Request Routing (ARR). How shall we back up that one? Do you want to play the "Screenshot/Print Game" or get creative with a little automation?

Yes, little Johnny in the back. I see you jumping up and down shouting, "Automation! Automation!"

Automation it is.

However this time, we won't be using Windows PowerShell (now stop crying, Johnny). We'll be using the built-in administration commands in IIS.

If you've played with the ARR role, it's storing configuration information that does nothing more than translate one FQDN to another. To restore the ARR role on that server (other than the server name and the actual features), you'll need the configuration for the ARR.

I will not take credit on this solution. The answer came from a brilliant fellow on serverfault.com as I was searching for the very same answer: How can I export URL rewrite rules?

You can use the command AppCmd to work with the IIS configuration. To pull out all the rules for ARR, you'll have to run the following commands:

C:\Windows\system32\inetsrv\appcmd list config "websitename/appname" -section:system.webServer/rewrite/rules –xml

C:\Windows\system32\inetsrv\appcmd list config -section:system.webServer/rewrite/globalRules –xml

C:\Windows\system32\inetsrv\appcmd list config -section:webFarms/ -xml

We can also make this a lot more readable in DOS. Why not swap out the directory name with a variable to boot?

SET APPCMD=C:\windows\system32\inetsrv\

%APPCMD%appcmd list config "websitename/appname" -section:system.webServer/rewrite/rules –xml

%APPCMD%appcmd list config -section:system.webServer/rewrite/globalRules –xml

%APPCMD%appcmd list config -section:webFarms/ -xml

This is of course relatively useless because it only dumps a pile of information on the screen. So we'll have to capture this. We'll have to go "old school" with a redirector. And we'll use a DOS variable for the folder name too.

Set Backup=C:\Backup\

%APPCMD%appcmd list config "websitename/appname" -section:system.webServer/rewrite/rules –xml > %BACKUP%rewriterules.xml

%APPCMD%appcmd list config -section:system.webServer/rewrite/globalRules –xml > %BACKUP%globalrewriterules.xml

%APPCMD%appcmd list config -section:webFarms/ -xml > %BACKUP%webfarms.xml

We could go even further with our backup process for Lync servers (or other servers, for that matter) to extend it to near disaster recovery scenarios. We could the get the memory, disk sizes, and server configuration! Nothing stopping us from doing that in Windows PowerShell. The output could be a simple CSV file too.

$Computer=(GET-WMIOBJECT Win32_computersystem)

$Ram=$Computer.TotalPhysicalMemory

$Servername=$Computer.Name

$Domain=$Server.Domain

$DiskInfo=GET-WmiObject –query 'Select * from Win32_Logicaldisk where DriveType = 3'

$DataOut = new-object PSObject

$DataOut = Add-Member –MemberType NoteProperty –name "ServerName" –Value $Servername

$DataOut = Add-Member –MemberType NoteProperty –name "PhysicalRam" –Value $Ram

$DataOut = Add-Member –MemberType NoteProperty –name "Domain" –Value $Domain

Foreach ($Disk in $DiskInfo)

{

$DataOut = Add-Member –MemberType NoteProperty –name "DriveLetter" –Value $Disk.DeviceID

$DataOut = Add-Member –MemberType NoteProperty –name "DriveSize" –Value $Disk.Size

}

$DataOut | Export-CSV C:\Backup\ServerConfig.csv

This should give you a starting point for getting all of the most critical information out of our small Lync environment. It is not so tricky to do. But extending this backup to a self-documenting system? There's an interesting thought!

Stop by tomorrow because I can sure smell something good cooking up on the Hey, Scripting Guy! Blog.

I invite you to follow the Scripting Guys on Twitter and Facebook. If you have any questions, send an email to the Scripting Guys at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then just remember, the Power of Shell is in You.

Sean Kearney, Windows PowerShell MVP and Honorary Scripting Guy 


PowerTip: Document Server's IP Addresses by Using PowerShell

$
0
0

Summary: Use Windows PowerShell to document the IP addresses on a server.

Hey, Scripting Guy! Question How can I use Windows PowerShell to easily go through my server environment and
          document the IP addresses in use on each machine?

Hey, Scripting Guy! Answer We can do this with a wee bit o' magic from the new Get-NetIPConfiguration cmdlet
          in Windows Server 2012 R2:

Get-NetIPConfiguration | Select-object InterfaceDescription -ExpandProperty AllIPAddresses

If you'd like to save it in a file, use the Export-CSV cmdlet:

Get-NetIPConfiguration | Select-object InterfaceDescription -ExpandProperty AllIPAddresses |
Export-CSV IPConfig.csv

Back to the Basics Part 1: Learn About the PowerShell Pipeline

$
0
0

Summary: Guest blogger and Microsoft PFE, Gary Siepser, talks about the basics of the Windows PowerShell pipeline.

Microsoft Scripting Guy, Ed Wilson, is here. This week we have a series of five posts that are written by PFE Gary Siepser as we head back to the basics with the Windows PowerShell pipeline.

Gary Siepser here (@PowerShellPFE). For Microsoft, I am a senior premier field engineer specializing in everything PowerShell. These days I find myself mostly teaching several Windows PowerShell classes to Microsoft customers. Check out Support: Premier Support Services to learn more.

Windows PowerShell has been around for a while and version 5.0 is coming soon. But every day we get new folks who want to learn about Windows PowerShell. I have taught beginner classes several times a month for years now.

As deep as I try to geek-out with Windows PowerShell, I always try to remember how much you can accomplish with so little work. In this series, we'll look at the simplicity and power of using the pipeline in Windows PowerShell to string together simple cmdlets into valuable and effective solutions.

Introduced in Windows PowerShell 3.0 (including the Windows PowerShell ISE), we have this awesome Show-Command pane that is on by default. This is such a wonderful way for a beginner to get started using Windows PowerShell. You can easily browse through commands, pick a command, get Help about that command, and even see what options a command has. Then to top it all off, you can fill out that command's parameters and execute, insert, or copy it. All of this makes getting started using Windows PowerShell a piece-of-cake and you don’t really have to know a thing about how it really works.

In the following image, you can see the Commands pane on the right side of the Windows PowerShell ISE screen. You can get to a similar GUI by running the Show-Command cmdlet from the Windows PowerShell console or the ISE.

Image of screen

The following image shows that a command was chosen, the Name parameter field was filled in with a service name, the Verbose common parameter was selected, and the Run button was pressed.

Image of menu

This command is automatically built for you and executed as shown in the following image:

Image of command output

Using the Show-Command GUI or Get-Command will help you to find a command and enable you use that command with little work. This is a great start, but the nature of most commands (both cmdlets and functions) are to be single-purpose.

Cmdlets do one job and do it well. To explain what I mean, think about a simple cmdlet like Get-Service. There is no way to control the sort order or filter services by their status. Those two needs are addressed by other single-purpose cmdlets. This might sound confusing at first, but it’s worth it. When you learn certain commands, like sorting or filtering, you can constantly apply that knowledge to new situations.

To solve our actual business problems, we often need to use several of these commands together to form the real solution. The Windows PowerShell pipeline takes simple commands, combines them, and solves our problems.

The pipeline in Windows PowerShell is a simple and elegant solution that you can use to string together multiple commands. The pipeline character in Windows PowerShell is the vertical bar (also called the pipe: | ). On most U.S. keyboards, it is found on the key with the backslash. You can press Shift + Backslash to get the pipe character. I’ve seen it in different places on keyboards in other languages, so look for it on yours.

The pipe character is used between commands to create the pipeline. We work from left to right down the pipeline. The output of one command effectively becomes the input of the next command.

In the following example you can see the basic structure of the pipeline followed by a simple example that gets all the services on your machine, sorts them by their status (such as Running or Stopped), and then formats them into a table that shows the Status and Name columns. This is a simple pipeline solution.

Image of command

In Windows PowerShell, we can think about the output of each command “flowing” down the pipeline, and this output is called Objects. Objects flow down the pipeline, not simply the text you see on the screen when you run each command by itself. This makes the pipeline considerably more powerful as objects are more structured data than plain text.

Although there is no limit on how you choose to use the pipeline and what commands you choose when structuring your pipeline, there are some common elements we see regularly in Windows PowerShell pipelines.

The pipeline has to start somewhere. We start by getting some data. We have to put something into the pipeline to do anything useful. I call this first part of the pipeline the "Getters.” Often this first command starts with the verb Get. However, there are plenty of commands that don’t start with Get that provide a great way to start things, for example Import-CSV, or maybe an external command we know from using the command prompt, such as nbtstat.exe.

The next phase of the pipeline we commonly see is “doing something with your data”—massaging it in some useful way. This ranges from commands like Sort-Object or Select-Object to filtering the pipeline with Where-Object. Plus there are many other commands that exist for the sole purpose of manipulating your objects (your data) in useful ways as part of the solution.

The last phase of common pipeline structure is to output or present your data. You can use one of the Format commands to present your data in a readable way, or maybe you want export your data to another format like CSV, XML, or JSON.

The following is a graphical representation of a common pipeline structure and two examples of pipelines that use this structure:

Image of commands

You can see that by using the pipeline in Windows PowerShell, we are able to easily bring together multiple single commands into a small, but effective, solution.

~Gary

Thank you, Gary. Be sure to join us tomorrow. In Part 2 of this series, Gary will more deeply explore the “Getters” and see how to start a typical pipeline.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Learn to Start the PowerShell Pipeline

$
0
0

Summary: Find cmdlets that permit starting the pipeline in Windows PowerShell.

 Hey, Scripting Guy! Question How do I find all the Get commands that allow me to start a pipeline?

Hey, Scripting Guy! Answer Although there are a number of ways, the Get-Command cmdlet has a parameter
          called -Verb for this purpose:

PS > Get-Command -Verb Get

CommandType Name          ModuleName      

----------- ----          ----------      

Alias  Get-ProvisionedAppxPackage     Dism      

Function Get-AppBackgroundTask      AppBackgroundTask   

Function Get-AppxLastError       Appx       

Function Get-AppxLog         Appx      

Function Get-AssignedAccess       AssignedAccess     

Function Get-BCClientConfiguration     BranchCache      

Function Get-BCContentServerConfiguration   BranchCache      

Back to the Basics Part 2: Learn about the Pipeline and "Getters"

$
0
0

Summary: Microsoft PFE, Gary Siepser, talks about the basics of using the Windows PowerShell pipeline and "getters."

Microsoft Scripting Guy, Ed Wilson, is here. This week, Gary Siepser, a Microsoft PFE is our guest blogger. Yesterday, we posted the first part of his series: Back to the Basics Part 1: Learn About the PowerShell Pipeline.

In in first post of this series, we looked at what the pipeline is and why you want to use it. We also outlined the common parts of the pipeline by introducing the “getters, doing something with your data, and outputting your data somewhere. In this post, we’ll focus on the first common portion of the pipeline, the “getters.”

Pipelines have to start somewhere. Like sending liquid down a real pipeline, we start the trip by putting something into the pipe. We need some data. In Windows PowerShell, this data is actually structured data in objects. Right now the objects aren’t that important for starting a pipe, but the sooner you start thinking "objects,” the more power you’ll put into the shell. The first part of the pipeline is going to be some kind of command that outputs the data you want to work with.

In Part 1, we investigated using the Show-Command pane in the ISE to find commands. Using that technique, you can find potentially thousands of sources of your data. Most of the time, the command you will use starts with the verb Get-. This is not surprising because this is the very reason the verb exists. In the Windows PowerShell SDK, the exact description is “Specifies an action that retrieves a resource.” For more information about verb choices, see Approved Verbs for Windows PowerShell Commands.

The following list is completely overwhelming and long, but take a look and appreciate how many Get- commands I see on my laptop (which is still a mere subset of what is possible on a Windows Server operating system with lots of roles and features).

Image of command output

If you made it this far, you deserve to know that there are 342 commands in this listed. I know that was a lot to look at, but I can’t stress enough how much coverage there is now with Windows PowerShell and how many things you can work with by using these commands.

Although this post is about the “getters,” and a majority of the time you are going to start your pipeline with one of these commands, there are also other great ways to start the pipeline.

Pipelines can start with external DOS commands, imports from other file formats (such as CSV and XML), or a variable. The bottom line is that we need some data—some objects from somewhere. Depending on which method you choose can greatly affect how you continue with the pipeline later. Let’s take a look at each of these techniques.

DOS commands   

Trusty old external DOS commands seem like they will never die (until they are literally removed from the operating sysem, I suppose). I always think to the common staples like ping.exe or ipconfig.exe. Now we have native Windows PowerShell cmdlets for both of those, but there are still some oldies-but-goodies out there. Think of aging stuff like nbtstat.exe (that is “NetBIOS over TCP statistics” for the old-timers).

When you run these external commands, you get back text. Although technically these lines of text are string objects in Windows PowerShell, they are in fact pretty simple objects that are unstructured. Working with this data in Windows PowerShell is not very easy. Parsing text often follows external commands. Even with the challenges, you can get done what you need to. Native Windows PowerShell commands are nearly always more desirable than external commands, especially when getting data.

Other file formats   

Importing data from other file formats is also a neat way to start the pipeline. It’s very common as an IT admin to move data around between systems, and common formats (like CSV) are a great medium to do so.

Import-CSV is a cmdlet in Windows PowerShell that does a fantastic job. It’s smart enough to look at the header row to determine what properties each object will get, and then turn each data row into one of those objects. The best part is that those objects (structured data), will travel down the pipeline and be usable for all the manipulation and outputting we want to do later in the pipeline. We’ll cover that in the next two posts in this series.

Import-CSV is shockingly easy to use. Take a look at the data in the following CSV file:

Image of file

Now take a look at how nicely Import-CSV brings in that data:

Image of command output

It’s that simple. In the next post when we talk about doing things with your data, you’ll see how to sort it. For now, here is an early peek:

Image of command output

You can see how easy it is. For more information, check out the Help file for Import-CSV. CSV is certainly not the only format you can import from, but it’s a good start. Look for other cmdlets that can import data from other formats.

Variables  

You can also start a pipeline with data you have already stored in a variable. A variable is simply a place to store your stuff. You’ll recognize variables because their name is usually proceeded by a dollar sign (for example, $Services). I don’t want to get deeply into variables, but here is a quick look at a basic way to save something into a variable that you can use to start your pipeline:

Image of command output

In this example, you can see that we stored the results of the Get-Service command into a variable called $MyServices. On the next line, we used this variable to start the pipeline. This really doesn’t end up being any different than using Get-Service to start the pipeline. Where using a variable is great is if I want to use this stored data more than once. I don’t need to get it all again. Why duplicate the effort when I can get it once and use the results over and over again.

By looking at these three techniques, you can see that starting a pipeline is really flexible. Always remember about searching for commands by using the Show-Command pane in the ISE and reading the Help to understand how to use them. In the next two posts, we will look at manipulating your data in the pipeline.

~Gary

Thanks Gary. Join us tomorrow for Part 3 of our Back to the Basics series.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Use Custom Delimiter with CSV File

$
0
0

Summary: Use a custom delimiter with Windows PowerShell when reading a CSV file.

Hey, Scripting Guy! Question Can I use a delimiter other than the comma ( , ) when reading from a CSV file?

Hey, Scripting Guy! Answer Import-CSV has a parameter dedicated for this purpose called -Delimiter:

Get-Help Import-Csv -ShowWindow

Image of Help file

You can easily use this during the import:

Image of command output

Image of command output

Back to the Basics Part 3: Do Something with Your Data

$
0
0

Summary: Microsoft PFE, Gary Siepser, further investigates the basics of the Windows PowerShell pipeline.

Microsoft Scripting Guy, Ed Wilson, is here. It's midweek already! Time sure flies, especially when you have a guest blogger for the week. Welcome back Gary Siepser for the third part in a series. To catch up, read:

In Part 2 of this series, we looked at how you start a pipeline. In this part, we’ll see some basic and easy-to-use commands that let us manipulate that data to suit our needs. 

First, let’s do a quick review of cmdlets. They are single-purpose commands that can be used together in a pipeline as building blocks for a real solution. Because most cmdlets truly are single purpose, they usually lack common functionality, such as exporting to other file formats or sorting the output. Often Get cmdlets don’t even have very rich filtering capabilities. This is intentional. We have other single-purpose cmdlets to address those needs.

Let’s also recall that the pipeline is simply a way to string commands together. The output of one command becomes the input of the next command. All of the cmdlets we are going to look at in this post were specifically designed to be used in the pipeline. As a matter of fact, if you try to start a line with these commands, they typically don’t work like you would expect. They were meant to be used in the pipeline, so we need to use them that way.

For the rest of this post, we’ll focus on four simple but key ways we need to work with our data:

  • Sorting
  • Simplifying
  • Counting
  • Filtering

The best part about the cmdlets that perform these feats is that they work with ANYTHING. They were designed to work with any objects coming through the pipeline. They even have the noun of Object to keep them generic. The big win is that you learn them once, and use them forever!

We’ll start with the simplest: Sort-Object. The Sort-Object cmdlet is so simple to use. There are really only two things to think about:

1. What you want to sort by

2. Ascending or descending sort

The latter is the easier one to talk about. If you want an ascending sort, don’t do anything. This is what the cmdlet does by default.

Now for choosing what to sort by...

Most of time, I will look at the unsorted results first to spot what property I want to sort by (or column if it’s a table). If I spot something, just use the Up arrow in the Windows PowerShell console to bring up the last command, and pipe it to the Sort-Object cmdlet. You’ll specify the property name that you want to sort by after the cmdlet.

Note  Sort is command alias for Sort-Object. I am not normally a big fan of using many shortcuts in Windows PowerShell, but this is one I really like because it keeps your pipeline very readable—almost like spoken language.

Take a look at the following examples of using Sort-Object. For more help with the command, like always, check out the Help topic (Get-Help Sort-Object –ShowWindow). 

Image of command output

Image of command output

Image of command output

If you try to use a property name that you saw (for example, the WS(K) column heading from Get-Process), and you find that something isn’t quite working as expected, there is a technique to solve your issue. This works for all the Object cmdlets we are going to cover.

The issue here is that the default view you get when you run a command can sometimes lie to us a little. There is some default formatting magic that occurs in Windows Powershell to make these default views look better (beauty is always in the eye of the beholder, of course). This magic can make it a little harder to look at column headings and use them with your cmdlets. Always try them first, but if it fails, Get-Member is your savior.

Get-Member is an investigative cmdlet that will show us what we are working with. Down the road, when you really start geeking-out with Windows Powershell and objects, Get-Member is truly a great asset. Even in the beginning stages of our Windows Powershell lives, we can get value from it without diving in too deeply. Pipe whatever you are working with to the Get-Member cmdlet, and it will show you a list of all the real properties for the object. For now, ignore anything that doesn’t have the word property in its MemberType column.

Image of command output

There is some truncation in the previous example to show a few different types of members without making you scroll too far.

Armed with Get-Member, you can now choose what property you are going to sort by. As I mentioned earlier, this applies to not only all the Object cmdlets in this post, but all across Windows Powershell. Get-Member will show you what you are really working with instead of the more “user-friendly” default views we normally see.

Now that we can sort our data, let’s move on to simplifying what you are working with. Select-Object is, in my opinion, the Swiss Army knife of Windows Powershell. It can really manipulate your objects a lot. To keep things simple right now, we’ll look at how it can strip down your objects to only the properties you want to deal with. This is really easy.

Follow the Select-Object (the alias is Select) cmdlet with a comma-separated list of the properties you want to keep. There is a really cool side effect of doing this. After you have simplified your objects, the default formatting I referred to earlier has really neat behavior. If you strip down an object to four or less properties, you will see them as a table. If you strip it down to five or more properties, you will get a list.

This is cool because default formatting isn’t normally dynamic. It’s a logical choice that Windows PowerShell makes for you, and I see a lot of folks using it for that reason. In Part 5 of this series, we will look at outputting your data. Using Select-Object reduces some need to directly control the output and formatting by dynamically choosing them for you.

Take a look at how this looks:

Image of command output

You can see that in the first example, there were only four properties, so we saw a table. The second example had five properties, and Windows PowerShell automatically generated a list. Also, because of the width of the command, I took advantage of line-continuation in Windows PowerShell by hitting ENTER after the pipeline character. If you are working in the ISE Console, press Shift + ENTER.

Select-Object can do so much more than this, but we want to keep things simple in this post and series. To see more, check out the Help for Select-Object (Get-Help Select-Object –ShowWindow). The examples in the Help show many different options.

Next, we’ll use Measure-Object to get a count of objects in the pipeline. (The alias is Measure. Are we seeing a trend with the alias names?) This is something I use all the time! There are several ways in Windows PowerShell to get this count, but I love just piping to Measure.

Measure-Object can get several other calculations for numeric properties such as sum and average. It can also analyze text for lines and characters, and analyze words for string objects and properties. For more information, check the Help file (Get-Help Measure-Object –ShowWindow).

Take a look at these examples for counting objects:

Image of command output

Lastly, we’ll look at some simple examples of filtering objects. We filter objects in the pipeline by using the Where-Object cmdlet. (Surprise, we have the alias: Where.) Using Where-Object can get a little advanced, and in this post, we are going to look at only using the simplified syntax. This easier-to-use and easier-to-look-at syntax was introduced in Windows PowerShell 3.0, and it covers a good majority of the filtering that I see with Where-Object.

To filter objects, we need to tell Where-Object what property we want to test, how we want to test it, and what value we are testing against. That may sound a little complicated, but it’s actually pretty straight-forward. Like all the other cmdlets, though, looking at the Help file will clear up all the ways that the cmdlet works (Get-Help Where-Object –ShowWindow).

Take a look at these examples of filtering by using Where-Object to see what I am talking about. I love that they are fairly high-level language and quite readable.

Image of command output

I can’t help but read these two example lines and think to myself that any IT admin is going to understand what is happening, even if they have never ever heard of Windows PowerShell. I like intuitive, and this is definitely it.

Before I close this post, I want to show one more example where we bring a few of these cmdlets together at the same time into a more complex, but still easy-to-understand pipeline:

Image of command output

Now that, my friends, is piping.

In Part 4, we will look at a few even cooler things that we can do with our data in the pipeline, for example, grouping by similar values, teeing our objects in two directions, and the original non-simplified syntax for Where-Object.

~Gary

Thank you, Gary, for sharing your time and knowledge.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

PowerTip: Sorting More than One Column

$
0
0

Summary: Learn to sort by more than one column in Windows PowerShell.

Hey, Scripting Guy! Question Can I use Windows PowerShell to sort by more than one column, and have the primary column be ascending
          and secondary column be descending?

Hey, Scripting Guy! Answer In the Help examples, you'll see that the Property parameter accepts a hash table in place of a
          real property name. In this hash table, you can specify the property to sort by and the order per property.
          Copy Example 5 from the Help file and edit to suit your needs.

Image of Help file


Back to Basics Part 4: More Ways to Manipulate Data

$
0
0

Summary: Microsoft PFE, Gary Siepser, talks more about the basics of the Windows PowerShell pipeline.

Microsoft Scripting Guy, Ed Wilson, is here. Today Gary Siepser delivers his Part 4 of his five part series.

To follow along, you can read:

In Part 3, we introduced several cool things you can do with your data. In this post, we will continue that investigation by looking at even cooler techniques. We’ll focus on:

  • Grouping your data
  • Using your data in the pipeline while you use it another way too
  • Advanced use of Where-Object filtering that we discussed in Part 2

Grouping data

Sometimes when you are working with typical IT admin-type information, it’s useful to get counts of various things. Often there are common values on objects. For example, when you are looking at a list of users, they all might have an office location. It is a great thing to be able to get a quick count of users per office.

The cmdlet Group-Object (the alias is Group) does a wonderful job of lumping together data based on common values. In our user per office example from Active Directory, you can easily pipe the user objects into Group-Object and tell it to group by the Office property. You will be pleasantly surprised at how quickly you get exactly what you are looking for.

Using the Group-Object cmdlet is actually pretty easy. Identifying the properties that you want to group by is a little more challenging. If you look back at Part 2 in this series, you will see how you can use the Get-Member cmdlet to see the available properties for your objects. That is only half the battle though, because it only makes sense to group objects where the data values have commonality. This is logical, and it would be true even if you were working in Excel to do the same thing. When you know what property you want to group by, you can use it as a parameter for Group-Object.

Group-Object has a number of interesting parameters in addition to what property you choose to group by. If you are truly interested in only the group names and counts (and not the individual object data—which is the case for me most of the time), there is a –NoElement property that will give you only those unique group names and counts. See the Help file for more information about extra things Group-Object can do (Get-Help Group-Object –ShowWindow).

Image of command output

The last example combines grouping with sorting, and it adds a parameter that we introduced in Part 3 of the series from the Select-Object cmdlet. This parameter allows you to grab a chunk from the top of your output. Recall that Select-Object is about choosing part of your objects, but I did call it the Swiss Army knife of Windows PowerShell. The –First parameter is simply another tool being used in the pocket knife. This example is cool because it shows you the five most popular verbs used by cmdlets on your system.

Do two things with your objects at the same time

There is a cmdlet called Tee-Object (the alias is Tee). It allows you to keep your stuff flowing down the pipe, but also store it in a variable for later or even in a text file for long term keeping. I have found this to be a really cool trick for scripts (I know we are focused on the pipeline, but it’s a cool trick).

There are times when I have a nice pipeline that does some cool stuff, but it might take a while. This happens a lot when I use cmdlets like Get-CIMInstance or Get-WMIObject to get information from a lot of distributed systems. Often I want to output that data to a text file, or even to a variable to use later in that script.

Because the pipeline takes a long time to finish, I see nothing on the screen the entire time that I am waiting. When you see nothing for too long, you start to wonder if it’s even working. Tee-Object can make the user experience a lot better because you can see the objects being output steadily as the pipeline does its work, and still get the results in a variable or text file after.

Tee-Object simply splits the objects coming down the pipe in two directions (that is why it’s called Tee). One direction is always to continue flowing down the pipeline, and the other is a choice between a text file and a variable. It’s very simple, use the –FilePath parameter for a file, and the –Variable parameter for a variable.

When you use the –FilePath parameter, there is another parameter called –Append that you can use to continue adding data to a file that already exists. Again, this is a particularly great trick for pipelines that take a long time.

Image of command output

Both of these examples show that we were able to see the results when running the pipeline, and then also in the text file and the variable. Look at these and imagine how this would be nice for a long pipeline. You get to see something the entire time it's running!

Revisiting the Where-Object cmdlet

This time around, we'll focus on the more traditional and advanced syntax of Where-Object. The advanced syntax is useful when you want more than a simple filter. You’ll remember from Part 3 of this series that the simplified syntax worked by simply picking the property you wanted to filter by, choosing a filter comparison type, and choosing the value you want to compare to.

The more advanced syntax requires a little bit more in the way of special characters. First of all, we are going to use a parameter of Where-Object called –FilterScript. The trick is that this parameter is the first position, meaning if you leave it off and give Where-Object the value, it knows you meant to use the –FilterScript parameter.

This is the way I normally see it used. Actually, I have found that in many cases, folks don’t even realize they are using a regular old parameter when they use Where-Object. They learned how the syntax works and “went with it”—without even knowing it is a parameter or the parameter’s name.

The value we want to use with the traditional syntax of Where-Object is called a script block in Windows PowerShell. Don’t be confused by the name, it’s just a way to give Windows PowerShell some script, and have that script be the argument. What is important is to realize that the code you have in the script block is going to be surrounded by {curly braces}.

Inside this script block, we need to tell Where-Object what criteria we are going to use to filter this object. Let’s take a look at a couple of comparisons of the simplified syntax vs. the equivalent filter using the traditional advanced syntax.

Image of script

Both examples are functionally the same.

Not only do you see the script block surrounded by curly braces, but you’ll notice a few other differences. The $_ automatic variable is in use. This is a pretty simple concept. It is a placeholder that represents the objects being piped to Where-Object.

Where-Object examines each object to see if it needs to be filtered. The special variable allows you to refer to each of those objects together in one script block. You can also interchangeably use $PSItem in place of $_. Either one works the same. $PSItem was introduced in Windows PowerShell 3.0 to give a more readable name and reduce the use of the underscore special character, if desired. I’m so used to the simplicity of the single character name that I stick with $_.

You’ll also notice that we need to use a more traditional way to access an object’s property. That is using a single dot. The single dot allows access to any object members, and the properties and methods for an object. Remember, as we learned in Part 3, you can use the Get-Member cmdlet to explore what is available for an object.

The only other difference is that when using a text value (a string) with the traditional syntax, you need to place the string in quotes.

You can see this is definitely not as pleasing to the eye, nor is it as easy for beginners who are new to Windows PowerShell. Luckily with this introduction in Windows PowerShell 3.0, you can use the simpler syntax. The traditional syntax only needs to be used when you want to do more than a simple test.

One common reason we need the traditional syntax is to combine multiple conditions at the same time. There are operators in Windows PowerShell for this purpose. The great news is they work just like you use them in spoken language. We have –and, –or, and –xor.

The –and is pretty simple: both sides need to be True. The –or means either side or both sides need to be True. Although lesser known, –xor is also really easy. It means one side or the other needs to be True, but not both at the same time.

Take a look at these examples to see how these operators can make your filters richer. In both examples, you will see I used sets of parenthesis to ensure Windows PowerShell compares things correctly in the right order. This is a good habit, though these particular examples wouldn’t have run any differently if I left them off. Parenthesis allow you to control the order of operations if you need them different than the default. It’s just like the algebra you learned in school as a kid.

Image of script

In both of these examples, we have multiple tests going on, thus the traditional Where-Object syntax is required. If you are new to Windows PowerShell, and you think this looks like a lot of confusing syntax, take it slowly. You’ll get it all figured out in time. However, feel some pity for those using Windows PowerShell for a while. Before version 3.0, this was the only way to filter with the Where-Object cmdlet.

There are all sorts of neat things you can do inside those curly braces. The thing to remember is that Where-Object is looking for a True or False result. You can literally put anything in those filters—they simply need to come out as True for the objects you want to keep flowing down the pipeline. Check out the Help file for more details (Get-Help Where-Object –ShowWindow).

As you can see, there are so many cool things you can do with your data when you have it in the pipeline. Parts 3 and 4 in this series have covered the basics and a few cool things, but there are many other great cmdlets that you can use to manipulate your objects. First, check out all the cmdlets that use the noun Object. Beyond them, look at all the script you see around and check out what others are doing in their pipelines.

In Part 5, the end of this series, we’ll learn about a few of the ways to output your objects at the end of your pipeline.

~Gary

Thank you, Gary! I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Looking for Folders and Files in PowerShell

$
0
0

Summary: Learn about looking for folders and files in Windows PowerShell.

Hey, Scripting Guy! Question Why does this command show me folders instead of files?

Dir | Where PSIsContainer -eq False

Hey, Scripting Guy! Answer In Windows PowerShell, use the automatic variables $True and $False to refer to Boolean values
          instead of the string True and False. To perform the comparison, Windows PowerShell converts
          the object on the right into the same type as on the left, so the string False is evaluated as a Boolean True.

In this case, you are converting a string into a Boolean value, so if the string has characters in it, it will
become a True. Only an empty string becomes a False. This is why your sample code gives you folders
instead of files. Try it like this and you will be a lot happier with the results:

Dir | Where PSIsContainer -EQ $False

Back to Basics Part 5: Outputting Data

$
0
0

Summary: Microsoft PFE, Gary Siepser, talks about outputting data via the pipeline in this exciting conclusion to a five part series.

Microsoft Scripting Guy, Ed Wilson, is here. Today brings an end to a week of guest blog posts by Gary Siepser. You can read the following posts to catch up with the previous days:

In Parts 3 and 4 of this series, we talked about a number of different things you can do with data coming down the pipeline. In Part 5, we are going to talk about what you do at the end of a pipeline. This can often be to output or present your data in some way. We’ll focus on formatting your objects to view them a certain way, getting them into simple text files, and exporting to other formats (like CSV and XML).

After you have some data in your pipeline and you have manipulated it the way you want, the last part of the pipeline is to output or present your data. You have likely already noticed that if you choose not to do anything, you will still see your data. Any time you have stuff in the pipeline, if you let that stuff hit the end of the pipeline, Windows PowerShell is going to show it to you in some way.

This is due to the default formatting system in Windows PowerShell. Formatting is simply putting this structured data (your objects) into a more humanly readable form. This usually takes the form of a table or a list.

This default look at our data is great, and I am really glad it is there, but very often we need to see that data presented in a different way. We use the formatting cmdlets to control exactly what that readable rendering should look like. We have the Format-Table, Format-List, and Format-Wide cmdlets to take care of this.

The most common format type I find myself using is a table. Tables are great for comparing object values to each other in a fairly concise way. Format-Table is our best friend for this. Like most of the Object cmdlets we have already covered, the format cmdlets are really easy to use. You simply need to tell Format-Table or Format-List what properties you want to be shown. Format-Wide focuses on only one property at a time.

Image of command output

Format-Table has a parameter that I see used all the time called –AutoSize. Generally, it squeezes everything to the left as tight as it can to fit more in. It also helps with values that are being truncated like the ones you see in the previous example.

Sometimes though, if you have really wide values in your columns, -AutoSize can backfire and cause columns on the right to be left off completely because there is not enough space. Notice the in the following example that the Status column didn’t make the result because of–AutoSize.

Image of command output

Over the years I have encountered a number of folks who would like to see –AutoSize turned on by default because they use it almost every time they use Format-Table. Introduced in Windows PowerShell 3.0, you can run the following command to set the parameter defaults:

$PSDefaultParameterValues['Format-Table:Autosize'] = $true
Now, when you run Format-Table, the output will always be “autosized”! This setting will be lost when you close Windows PowerShell, but you can set it in a profile script to have it run each time you launch Windows PowerShell. For more information, see Help about profiles (Get-Help About_Profiles –ShowWindow).

Tables are great, but they are limited by the amount of width you have. There is a –Wrap parameter that can help with the width issue, but still there is only so much space in a table. This is where a list comes in to play.

I think of Format-List as the report writer. It gives you a vertical list of objects and properties. Each property has as much width as it needs and will wrap to next line if it needs to. Like Format-Table, Format-List needs to know which properties you want to show up.

When you are exploring objects beyond using Get-Member (discussed in Part 3), you can use Format-List followed by an asterisk ( * ) to represent all properties. Take a look at these examples for Format-List:

Image of command output

Format-Wide is really useful when you need to see only one thing, such as the Name property, but you want to squeeze as many objects on the screen as you can. Like the Format-Table cmdlet, there is an –AutoSize parameter to allow Format-Wide to maximize the numbers of columns without truncating your data.

Image of command output

Now that we know how to format our data to see exactly what we want to see, let’s see about how we can record this into a text file. There are a couple of different choices for this. I prefer the Out-File cmdlet, but there is also a Set-Content cmdlet.

The biggest difference between the cmdlets is that Out-File can come after formatting in the pipeline, but Set-Content cannot. Set-Content only works well when the objects coming through the pipeline are already strings. Out-File records whatever you could normally see in the Windows PowerShell console, so I think it’s the better cmdlet, especially for beginners.

Image of command

Image of command output

Text files are great for log type files and simple long term keeping, but sometimes we need a richer data format. Many IT admins are already familiar with a format called CSV. CSV format is a text file that contains rows of values that are delimited by a character (a comma by default). However, the delimiter can be any character. Commas, tabs, and pipes seem to be the most common, in my experience.

We discussed the Import-CSV cmdlet in Part 2. Now we will look at the Export-CSV cmdlet. It’s a really simple cmdlet. Whatever gets piped in to it gets converted to simple text in the CSV file you create. It will export all the properties in the pipeline to that CSV file.

Remember, if you look at your objects without formatting in Windows PowerShell, you are going to see the default formatting we learned about earlier in this post. This is usually a reduced set of the properties for your objects—generally in some decent looking format.

Export-CSV will export ALL the properties for your objects, so you might end up with an unexpected amount of data in the CSV file. The great news is, if you have been following this series, you already know how to deal with this. The Select-Object cmdlet that we covered in Part 3 allows you to reduce the data to only what you want in the pipeline prior to running the Export-CSV:

Image of command

Image of command output

Image of command

Image of command output

You can see in the first example that there is a lot of data in the CSV file. This is because process objects in the pipeline have a large number of properties and Export-CSV lists them all. In the second example, you can see how the data is simplified because Select-Object is in the pipeline prior to the export, and it stripped the data to only the three selected properties. You can also see in the second example that I exported the CSV file by using a tab as the delimiter instead of the default comma.

Another confusing thing about Export-CSV is the #TYPE ... line at the top of file. This line is used specifically when Windows PowerShell imports that file, but it could cause issues if you plan to use the CSV file with some other system that won’t understand the line. Export-CSV has a parameter switch called –NoTypeInformation that you can use to cause Windows PowerShell to leave off that #TYPE ... line.

Many of the things we run in Windows PowerShell are lost when Windows PowerShell is closed. Now that we are storing data in the file system (which persists beyond a closed Windows PowerShell window), we might notice that this is an interesting way we can “save” or “persist” our objects that are using a CSV file. One limitation is that all values import as strings from a CSV file. A format that gets around this limitation is XML, and you can use the Export-CliXML cmdlet.

The Export-CliXML cmdlet works like Export-CSV, but it uses a much richer and more complex XML format for the file. This format retains more information about the objects, including the data type of the properties.

Image of command output

When you look at these examples, you can see how we can export to a rich format like XML (we are only looking at the first 10 lines), and then bring that data back in to Windows PowerShell and use it as if we just ran the original Get-Process.

There are so many things you can get done with your pipeline. This post has investigated some of the output abilities, but take time to explore all the core commands in Windows PowerShell.

I’ve been using Windows PowerShell for years. On a daily basis, I still feel like I discover cool new things I can do with Windows PowerShell, and especially the pipeline.

As I bring this series to a close, I hope you can see that the pipeline in Windows PowerShell is not simply a way avoid learning how to script. The pipeline is this wonderfully intuitive result of well-designed, single-purpose commands, coupled with the object-based nature of Windows PowerShell. It’s a great way for you to accomplish so much with so little. And you can do it in a way that is extremely readable and easy to modify and maintain going forward.

Go forth and solve the world’s problems one pipeline at a time. There is some Windows PowerShell geekiness for you!

~Gary

Thanks, Gary, for such a great series this week.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

PowerTip: Difference Between XML PowerShell Cmdlets

$
0
0

Summary: Understand the difference between XML cmdlets in Windows PowerShell.

Hey, Scripting Guy! Question What is the difference between the Windows PowerShell cmdlets, Export-CliXML and ConvertTo-XML?

Hey, Scripting Guy! Answer The Help file for ConvertTo-XML says:

"This cmdlet is similar to Export-CliXML, except that Export-CliXML stores the resulting XML in a file.
ConvertTo-XML returns the XML, so you can continue to process it in Windows PowerShell."

The Export verb encapsulates your objects in a persistent data store (such as a file) or into an
interchange format. The ConvertTo verb simply changes the objects in the pipeline for continued use.
If you follow ConvertTo-XML with Out-File, you would get similar results to Export-CliXML.

Weekend Scripter: Using Try, Catch, Finally Blocks for PowerShell Error Handling

$
0
0

Summary: Microsoft PFE, Ashley McGlone, talks about using Try, Catch, Finally blocks for error handling in Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. Today’s guest blogger is Ashley McGlone, a Microsoft premier field engineer. Ashley is a popular speaker at our Windows PowerShell Saturday events. He regularly blogs about Active Directory and Windows PowerShell at Goatee PFE. You can follow him on Twitter as @GoateePFE. Take it away, Ashley...

Why do scripts have errors? That is a long philosophical debate, and there is more than one correct answer. The generally accepted answer is that they are written by humans, and humans are not perfect. Even when considering all of the reasons there are errors in scripts, the root cause is usually a difference in expectations. I expect the code or data to be X, but really it is Y. And that is why we need error handling.

There are many ways to handle errors in Windows PowerShell, including:

  • $Error.Clear(); Do-Something; If ($Error) {..} Else {..}
  • Trap
  • $ErrorActionPreference

Try, Catch, Finally is similar to a Trap block. Trap blocks generally catch any errors in the scope of the entire script or function. The beauty of Try, Catch, Finally is that it is like a localized Trap for a specific block of commands. This gives you great flexibility in your error handling. It generally works like this:

Try {

 # Do something tricky

}

Catch {

 # Run this if a terminating error occurred in the Try block

 # The variable $_ represents the error that occurred

 $_

}

Finally {

 # Always run this at the end

}

Tip  Introduced in Windows PowerShell 3.0, you can use CTRL-J in the ISE to insert a Try, Catch, Finally snippet template to save you some typing.

We can also catch multiple errors. Here is an example from the ISE snippet:

try

{

 1/0

}

catch [DivideByZeroException]

{

 Write-Host "Divide by zero exception"

}

catch [System.Net.WebException],[System.Exception]

{

 Write-Host "Other exception"

}

finally

{

 Write-Host "cleaning up ..."

}

Finding .NET exceptions to catch

Following the Catch keyword, you can add .NET exception types as shown in the previous script example. (Fancy programmers call errors “exceptions.”) These are optional. So where can I find that fanciness to put after the Catch? You can sometimes find these on MSDN. For me, the fastest way is using this little trick:

$Error[0] | fl * -Force 

Look at the following example output when we try to divide by zero. Then notice the $Error output from the second command. Usually, the .NET exception follows the ‘-->’ in the output:

PS C:\> 1/0

Attempted to divide by zero.

At line:1 char:1

+ 1/0

+ ~~~

 + CategoryInfo   : NotSpecified: (:) [], RuntimeException

 + FullyQualifiedErrorId : RuntimeException

 

PS C:\> $Error[0] | fl * -Force

PSMessageDetails  :

Exception    : System.Management.Automation.RuntimeException: Attempted to divide by zero. -->

      System.DivideByZeroException: Attempted to divide by zero.

       --- End of inner exception stack trace ---

       at System.Management.Automation.IntOps.Divide(Int32 lhs, Int32 rhs)

       at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)

       at System.Management.Automation.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)

       at   System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)

TargetObject   :

CategoryInfo   : NotSpecified: (:) [], RuntimeException

FullyQualifiedErrorId : RuntimeException

ErrorDetails   :

InvocationInfo  : System.Management.Automation.InvocationInfo

ScriptStackTrace  : at <ScriptBlock>, <No file>: line 1

PipelineIterationInfo : {}

That’s how we find what to catch (or trap) when handling errors. You have to produce the error once, get the exception string from the extended $Error details, and then put that into square brackets following Catch. In this case either of the following would work:

catch [DivideByZeroException]

catch [System.DivideByZeroException]

This works for most error handling situations.

Tap...tap...tap...Is this thing on?

Sometimes Try, Catch, Finally will not catch your error. That’s because there are two kinds of errors in Windows PowerShell: terminating and non-terminating. For example, when I type:

PS C:\> dir HKLM:

I get errors in the middle of the output, but it keeps going. That is called a non-terminating error. However, if I try to divide by zero as in the previous example, that is a terminating error that stops the entire script.

You can force errors to terminate and hit your Catch block by using either of these methods:

  • $ErrorActionPreference = ‘Stop’
  • Use the common parameter: -ErrorAction Stop

In the interest of time, I will refer you to this previous blog post for a good explanation about how this works: 2014 Winter PowerShell Scripting Games Wrap Up #2.

How I’ve used Try, Catch, Finally

Most of my scripting revolves around the Active Directory module. Recently I was trying to use Get-ADObject with the ErrorAction parameter. Unfortunately, the cmdlet did not seem to obey the ErrorAction common parameter very well.

# No joy

$a = Get-ADObject -Identity $Id -Properties $Prop -ErrorAction SilentlyContinue

I need this functionality, because sometimes the object I was querying may not exist. This syntax would break the script if an error occurred, ignoring the ErrorAction parameter. To work around this, I enclosed the offending line of script in a Try block, and then I handled the error in the Catch block. Here is what I used:

try {

 $a = Get-ADObject -Identity $Id -Properties $Prop

}

catch {

 $a = $null

}

Notice that I left off the optional Finally block. This code met my needs perfectly.

I hope you’ve enjoyed learning about Try, Catch, Finally today. Don’t forget to read the Help for more information:

PS C:\> Get-Help about_Try_Catch_Finally

See these Windows PowerShell Help topics for related information:

  • about_Preference_Variables
  • about_CommonParameters
  • about_Throw
  • about_Trap

~Ashley

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Viewing all 2129 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>