Quantcast
Channel: Hey, Scripting Guy! Blog
Viewing all 3333 articles
Browse latest View live

Weekend Scripter: Use PowerShell to Meter Resources on Hyper-V Windows Server 2012

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell 3.0 to do Hyper-V Resource Metering on Windows Server 2012.

Microsoft Scripting Guy, Ed Wilson, is here. Well, Charlotte looked like someone had taken a huge can of polyurethane and sprayed the entire city—multiple times. Ok, so it is sort of pretty the way the city glistens in the sun with a thick layer of ice encapsulating the city, but dude, it is dangerous. So, the Scripting Wife and I headed out to the beach. I am sitting in one of those funky coffee houses near the beach, writing my blog posting for today, watching the waves, the surf, and the sand with a nearly unobscured view.

Yes, the Carolina beaches are great in the winter—when there are very few tourists to clutter things. Some restaurants close for the “off season,” but Teresa and I have discovered those types of restaurants are not the sort that we like to eat in anyway. We prefer the small, family-owned restaurants that have been in business for 50 years, and because of the quality of their food, and their loyal customer base, they do just fine year round.

Checking on status of Resource Metering

Now, it is possible to use performance counters to see how a virtual machine performs. It is also possible to use performance counters to see how the host (the server that hosts the virtual machines) performs. In fact, I wrote an entire series of articles talking about using performance counters with Windows PowerShell (in fact, one of my talks at the PowerShell Summit will be on what I call PoshMon). What was missing was a way to view the resource consumption of the virtual machine related to the host. The Introduction to Resource Meteringblog post written by Lalithra Fernando on the Virtualization Blog is an excellent place to start. Lalithra also wrote a blog post called How to Use Resource Metering with PowerShellwhich is also a good introduction.

Exam note  One of the objectives on the Exam 70-140: Installing and Configuring Windows Server 2012is configure Resource Metering, and so if you are working on your new MCSE for Server Infrastructure, you will want to know this material. Of course, if you are running or thinking about running Hyper-V on Windows Server 2012, you will want to know this information as well.Like I said yesterday, I like the MCSE exams because they help me to come up to speed quickly on a new product by forcing me to learn about the new features.

So, the first thing I need to do is to check on the status of Resource Metering on my Hyper-V server. To do this, I use the Get-VM cmdlet from the Hyper-V module to return virtual machine objects, and I pipe these to the Select-Object cmdlet, and I choose the name and the ResourceMeteringEnabledproperties. This command is shown here along with the associated output from the command.

Note  Keep in mind that the Get-VM and other cmdlets from the Hyper-V require admin rights to run, and therefore, if you are doing this on Windows 8, you will need to start Windows PowerShell with admin rights.

14:34 C:\> get-vm | select name, resourcemeteringenabled

Name                                                         ResourceMeteringEnabled

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

c1                                                                             False

C2                                                                             False

DC1                                                                            False

sql1                                                                           False

Enabling Resource Metering

Well, the next thing I need to do is to enable Resource Metering. To do this, I use the Enable-VMResourceMetering cmdlet. I can enable Resource Metering for a specific machine, such as for SQL1, by specifying the –VMName parameter. The command to do this is shown here (keep in mind that nothing returns from this command).

Enable-VMResourceMetering -VMName sql1

Exam ALERT   The default parameter set for the Enable-VMResourceMetering is VMName, and therefore, you can simply supply the name of the virtual machine Enable-VMResourceMetering SQL1. But, there are three parameter sets: VMName, VM, and ResourcePoolName. To make matters worse, ResourcePoolName has an alias of Name. Keep in mind, VMName is the name of the virtual machine, VM is a virtual machine object (such as returned by Get-VM) and ResourcePoolName and Name are the names of virtual machine resource pools. There is no alias for VMName or VM. The following illustrates available parameter aliases.

15:31 C:\> gcm Enable-VMResourceMetering | select -expand parameters | % {$_.values} |

? aliases | select name, aliases

Name                                       Aliases

----                                       -------

ResourcePoolName                 {Name}

Verbose                                    {vb}

Debug                                      {db}

ErrorAction                                {ea}

WarningAction                           {wa}

ErrorVariable                              {ev}

WarningVariable                         {wv}

OutVariable                                {ov}

OutBuffer                                  {ob}

 

If I want to, I can enable Resource Metering on all of the virtual machines by piping the results from Get-VM to the Enable-VMResourceMetering cmdlet, as shown here.

get-vm | Enable-VMResourceMetering

Getting the Resource Metering report

To get the report of metered resources, use the Measure-VM cmdlet. The default parameter set is VMName, and therefore, the parameter can be left out. The VMName parameter accepts an array, and therefore, I can obtain information from more than one virtual machine at a given time.

The following illustrates obtaining Resource Metering reports from one and from two virtual machines. The syntax is shown here.

Measure-VM dc1

Note   When a virtual machine is offline, it reports 0.

The following image illustrates using this command, as well as the command to measure two virtual machines.

Image of command output

Getting a metering report for all virtual machines

I can use the Get-VM cmdlet and pipe the returned VirtualMachine objects to the Measure-VM cmdlet to obtain a report on all of my virtual machines. The command is shown here.

get-vm | Measure-VM

The command and its output associated used to measure all virtual machines are shown in the image that follows.

Image of command output

But realize this IS Windows PowerShell, and therefore, everything is an object. This means I am not limited to the output appearing above. I use the Get-Member cmdlet (gm is an alias) to see what my options are. The command and its output are shown here.

16:02 C:\> get-vm | Measure-VM | gm -MemberType *property 

TypeName: Microsoft.HyperV.PowerShell.VMMeteringReportForVirtualMachine 

Name                        MemberType    Definition

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

AvgCPU                      AliasProperty AvgCPU = AverageProcessorUsage

AvgRAM                      AliasProperty AvgRAM = AverageMemoryUsage

MaxRAM                      AliasProperty MaxRAM = MaximumMemoryUsage

MinRAM                      AliasProperty MinRAM = MinimumMemoryUsage

TotalDisk                   AliasProperty TotalDisk = TotalDiskAllocation

AverageMemoryUsage          Property      System.Nullable[int] AverageMemoryUsage...

AverageProcessorUsage       Property      System.Nullable[int] AverageProcessorUs...

ComputerName                Property      string ComputerName {get;}

MaximumMemoryUsage          Property      System.Nullable[int] MaximumMemoryUsage...

MeteringDuration            Property      System.Nullable[timespan] MeteringDurat...

MinimumMemoryUsage          Property      System.Nullable[int] MinimumMemoryUsage...

NetworkMeteredTrafficReport Property      Microsoft.HyperV.PowerShell.VMPortAclMe...

TotalDiskAllocation         Property      System.Nullable[int] TotalDiskAllocatio...

VMId                        Property      guid VMId {get;}

VMName                      Property      string VMName {get;}

Sorting the output

I am not too impressed with the random order of the output. What I am concerned with is the amount of CPU utilization. So, I sort the output by AvgCPU (I know I can do this because of the output from the Get-Member cmdlet). Here is the command I use to sort the output by average CPU usage.

get-vm | Measure-VM | sort avgCPU -Descending

The command and its associated output are shown here.

Image of command output

Well, that is about it for now. I want to head down to the beach and take a few pictures before it gets too late. Join me tomorrow when I will continue this discussion about Hyper-V on Windows Server 2012.

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: Find Printers That Use 32-bit or 64-bit drivers

$
0
0

Summary: Use Windows PowerShell 3.0 on Windows 8 to find print devices that use 32- or 64-bit drivers.

Hey, Scripting Guy! Question How can I find print devices on my computer running Windows 8 that use 32-bit or 64-bit drivers?

Hey, Scripting Guy! Answer Use the Get-PrinterConfiguration cmdlet and use the Where-Object (? Is an alias) to filter out the printerenvironment property. Use the match operator to find either 64 or 32 as your needs require. Below are examples of this technique.

Get-PrinterDriver | ? printerenvironment -match 64

Get-PrinterDriver | ? printerenvironment -match 32

Use PowerShell to Configure Hyper-V Resource Metering

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell 3.0 to configure Hyper-V Resource Metering on Windows Server 2012.

Microsoft Scripting Guy, Ed Wilson, is here. Well, today is Monday, and the first thing I do on Monday is update the Help on Windows PowerShell 3.0. I use the command that is shown here.

Update-Help -Module * -Force

Note  I need to open the Windows PowerShell console with admin rights to update Help.

Once I have updated Help, I am prepared to start the week.

Exam note  One of the objectives on the Exam 70-410: Installing and Configuring Windows Serve 2012is configure Resource Metering, and so if you are working on your new MCSE for Server Infrastructure, you will want to know this material. Of course, if you are running or thinking about running Hyper-V on Windows Server 2012, you will want to know this information as well. The Introduction to Resource Meteringblog post written by Lalithra Fernando on the Virtualization Blog is an excellent place to start. Lalithra also wrote a blog article called How to Use Resource Metering with PowerShell, which is also a good introduction.

Use PowerShell to configure Resource Metering

One of the things is a bit confusing about Hyper-V Resource Metering on Windows Server 2012 is that I must enable Resource Metering on the individual virtual machine, but if I want to set the Resource Metering interval, I need to do that on the server that hosts the virtual machines.

Note  This is the second article in a series about Hyper-V and Windows PowerShell. It is also the fourth article in a series I have written about the MCSE exam 70-410.

Therefore, to configure the Resource Metering interval, I need to use the Set-VMHost cmdlet. I can do this remotely, if my logged on account has rights to the remote Hyper-V server. This is because the cmdlet has a –computername parameter, but no –credential parameter. Of course, I can wrap the thing by using Windows PowerShell remoting, and run the command on multiple remote Hyper-V servers.

The thing that is really confusing about configuring Resource Metering is that the ResourceMeteringSaveInterval parameter requires a TimeSpan object as the input parameter. Also, the parameter only accepts whole hour values—couple this with an error in the Help example, and it is really a challenge to get this thing to work properly. (Oh, did I say that it will accept lots of things, not generate an error, and not make the change?)

So, the first thing I do is follow the example in the Help, but an error occurs. Here is the command I typed:

Set-VMHost -ResourceMeteringSaveInterval 02: 00:00

Image of command output

Well, maybe I do not need to do all that. Besides, it only accepts values from 1 – 24 hours, in whole numbers, so why should I type all those colons and stuff. So I try the following command:

Set-VMHost -ResourceMeteringSaveInterval 3

Cool, no errors come back. But when I check the VMHost, I see the ResourceMeteringSaveInterval has not changed. These commands are shown here.

16:52 C:\> Set-VMHost -ResourceMeteringSaveInterval 3

16:56 C:\> Get-VMHost | select resource*

ResourceMeteringSaveInterval

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

01:00:00

So, I try it with a leading zero. Again no error returns, but no change either.

Set-VMHost -ResourceMeteringSaveInterval 03

First create a legitimate TimeSpan

Well, dude, this is NOT really that hard. Because I KNOW how to create a new TimeSpan, in fact, the cmdlet is New-TimeSpan, as shown here.

17:00 C:\> New-TimeSpan -Hours 3

Days              : 0

Hours             : 3

Minutes           : 0

Seconds           : 0

Milliseconds      : 0

Ticks             : 108000000000

TotalDays         : 0.125

TotalHours        : 3

TotalMinutes      : 180

TotalSeconds      : 10800

TotalMilliseconds : 10800000

So, all I have to do is store the TimeSpan in a variable and use that variable to configure the Resource Metering save interval, as shown here.

$rm = New-TimeSpan -Hours 3

Set-VMHost -ResourceMeteringSaveInterval $rm

Get-VMHost | select resource*

The image shown here illustrates using these commands, as well as the output associated with each cmdlet.

Image of command output

Simplify the process

Well, so I found out I could actually change the value—that is good news at least. So now, of course, I want to see if I can simplify the process. The first thing I decide to do is to put the New-TimeSpan cmdlet in the ResourceMeteringSaveInterval parameter slot. Once I make the change, I use the up arrow and retrieve the Get-VMHost command where I choose the Resource* property. The output shows that the command was successful.

17:04 C:\> Set-VMHost -ResourceMeteringSaveInterval (New-TimeSpan -Hours 2)

17:09 C:\> Get-VMHost | select resource*

ResourceMeteringSaveInterval

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

02:00:00

Well, that is cool, what about if I cast it to a TimeSpan object? I love casting stuff in Windows PowerShell. I think it is both elegant and useful. So, I use the [timespan] type accelerator to cast 01 to a TimeSpan object. The results appear here.

17:09 C:\> [timespan]01

Days              : 0

Hours             : 0

Minutes           : 0

Seconds           : 0

Milliseconds      : 0

Ticks             : 1

TotalDays         : 1.15740740740741E-12

TotalHours        : 2.77777777777778E-11

TotalMinutes      : 1.66666666666667E-09

TotalSeconds      : 1E-07

TotalMilliseconds : 0.0001

Well, it worked, but the problem is that I created a TimeSpan that is equal to 1 tick, and not to 1 hour. Bummer. So I add some zeros and look to see what happens. The output appears in the following image.

Image of command output

I now know that I can use [timespan]"01:00:00" and create a legitimate TimeSpan that measures 1 hour. But can I make it any easier? I drop a couple of zeros, and as shown here, it works.

17:14 C:\> [timespan]"01:00"

Days              : 0

Hours             : 1

Minutes           : 0

Seconds           : 0

Milliseconds      : 0

Ticks             : 36000000000

TotalDays         : 0.0416666666666667

TotalHours        : 1

TotalMinutes      : 60

TotalSeconds      : 3600

TotalMilliseconds : 3600000

Groovy, that worked as well. I am confident that it will work for the Set-VMHost cmdlet as well, but the only way to ensure that is to use it directly. So here goes:

Set-VMHost -ResourceMeteringSaveInterval [timespan]"12:00"

Bummer, an error occurs. I modify the command and group the [timespan]”12:00”. The revised command is shown here.

Set-VMHost -ResourceMeteringSaveInterval ([timespan]"12:00")

This time the command does not generate a command, so I use the Get-VMHost cmdlet to see if it worked. As shown in the following image, the command works fine.

Image of command output

Well, I know that Windows PowerShell does automatic type conversion, and I also know from the previous errors that the –ResourceMeteringSaveInterval expects a TimeSpan object. If I can convert 01:00 to a TimeSpan, will the parameter accept it? Let’s see …

17:18 C:\> Set-VMHost -ResourceMeteringSaveInterval 01:00

17:22 C:\> Get-VMHost | select resource*

ResourceMeteringSaveInterval

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

01:00:00

Yep, it works.

Summary

I typed a lot of commands in this article. What worked? Well, storing a TimeSpan object in a variable works, as shown here:

$rm = New-TimeSpan -Hours 3

Set-VMHost -ResourceMeteringSaveInterval $rm

Also, creating the TimeSpan object at the ResourceMeteringSaveInterval also worked, as shown here:

Set-VMHost -ResourceMeteringSaveInterval (New-Timespan -Hours 2)

Set-VMHost -ResourceMeteringSaveInterval ([timespan]"12:00")

Because Windows PowerShell does automatic type conversion, I can also supply a value that casts to a TimeSpan object, as shown here.

Set-VMHost -ResourceMeteringSaveInterval 01:00

I can also drop the leading zero if I wish, because the following command also works.

Set-VMHost -ResourceMeteringSaveInterval 5:00

Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

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: Easily Find the Memory Configuration of Your Virtual Machines

$
0
0

Summary: Use Windows PowerShell 3.0 on Windows Server 2012 to easily find the memory configuration of your Hyper-V virtual machines.

Hey, Scripting Guy! Question How can I easily find the memory configuration on my Windows Server 2012 Hyper-V virtual machines by using Windows PowerShell?

Hey, Scripting Guy! Answer Use the Get-VM cmdlet and pipe the results to the Get-VMMemory function, as shown here.

Get-VM | Get-VMMemory

 

Use PowerShell to Reset Hyper-V Resource Metering

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell 3.0 to reset Hyper-V Resource Metering.

Hey, Scripting Guy! Question Hey, Scripting Guy! Ok, I have this problem here at work. We have upgraded our servers running Windows Server 2008 R2 to Windows Server 2012. We are running Hyper-V, and we need to get a resource report each month to cross-charge other departments for the computing resources they use. Here is the problem. I read your article last week about resource metering, and I told my boss I had found the problem. He immediately said, “Well that may work this month, but what about next month.” I stood there looking like a deer in the headlights while he explained, “If we tell a department they use xyz resources this month, how do we get a fresh number for next month? Are we supposed to keep adding and subtracting and all that to come up with new numbers?” Please help me. I am the one who told my boss that I thought we could do what we need to do by using Windows Server 2012 and that we did not need to buy a new product to manage our resources. You see, my boss is like a wookiee, and I don’t want to make him mad.

—JJ

Hey, Scripting Guy! Answer Hello JJ,

Microsoft Scripting Guy, Ed Wilson, is here. Well, this morning things are cool. In fact, the entire house is a bit cool because outside it is freezing. I know, I live in the Deep South, and I should not complain about cold, because our cold is really quite warm, when compared to places like Nome, Alaska. But, hey, to me it feels cold.

Anyway, I am up this morning because I am making an “Industry Leadership” live meeting with a group of Microsoft PFEs in the UK. I am talking about the things I did to help to raise my profile in the community. It is kind of cool, and I am glad to help out. (I am also honored to be invited to speak to this group of way-cool and talented people.)

Anyway, JJ, you do not need to worry about upsetting your wookiee manager. In fact, after today’s article, you will need to worry about escaping a wookiee hug instead.

Exam note  One of the objectives on the Exam 70-410: Installing and Configuring Windows Server 2012is configure Resource Metering, and so if you are working on your new MCSE for Server Infrastructure, you will want to know this material. Of course, if you are running or thinking about running Hyper-V on Windows Server 2012, you will want to know this information as well. The Introduction to Resource Meteringblog post written by Lalithra Fernando on the Virtualization Blog is an excellent place to start. Lalithra also wrote a blog post called How to Use Resource Metering with PowerShell, which is also a good introduction.

Use PowerShell to see how long Resource Metering runs

Note  This is the third article in a series about Hyper-V and Windows PowerShell. In the first article, I talked about using PowerShell to Meter Resources on Hyper-V Windows Server 2012. In the second article, I discussed using PowerShell to Configure Hyper-V Resource Metering. This article is also the fifth post in a series I have written about the MCSE exam 70-410.

Resetting Hyper-V Resource Meter counters is actually pretty easy—after all, there is a dedicated Windows PowerShell cmdlet to use to accomplish the task. If you need to do this on a monthly basis, use the Task Scheduler to create a task to run the cmdlet. Set it for 1 minute after midnight on the first day of the month—if that is your billing cycle—and you are good to go.

To see how long it has been since the Resource Metering counters have been reset, I use the Get-VM cmdlet to return a VirtualMachine object, and I pipe the object to the Measure-VM cmdlet. I then select the MeteringDuration property. The command below illustrates this technique.

10:24 C:\> get-vm -VMName c1 | measure-vm | select meter*

MeteringDuration

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

00:31:33.8220000

If I want a report for all of my virtual machines, I only need to change the VMName property value to a wildcard. Once I do this, I decide I need to add the VMName property to the output. The revised command is shown here.

10:40 C:\> get-vm -VMName * | measure-vm | select vmname, meter*

VMName                                     MeteringDuration

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

sql1                                       1.19:17:49.4140000

DC1                                        1.19:02:24.8570000

C2                                         1.19:02:25.6450000

c1                                         00:33:02.7300000

Reset the Resource Metering counters

To reset the Resource Metering counters for a single virtual machine I use the Get-VM cmdlet and specify a single computer name. I pipe the resulting VirtualMachine object to the Reset-VMResourceMetering cmdlet. This command is shown here.

get-vm -VMName c1 | Reset-VMResourceMetering

Nothing returns from running the previous command, so I use the Get-VM cmdlet to return a VirtualMachine object, and I pipe it to the Measure-VM cmdlet to obtain the Resource Metering report for the virtual machine. I then select the MeteringDuration property to see if the counter has been reset. This command is shown here, and it tells me that the counters were reset 24 seconds ago.

10:42 C:\> get-vm -VMName c1 | measure-vm | select meter*

MeteringDuration

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

00:00:24.8590000

To reset the Resource Metering counters for all virtual machines on the host I use a wildcard to obtain all virtual machines on the local computer. I pipe the returned VirtualMachine objects to the Reset-VMResourceMetering cmdlet. The command is shown here.

get-vm -VMName * | Reset-VMResourceMetering

As before, nothing returns from running the Reset-VMResourceMetering cmdlet. To verify the changes took effect, I use the UP arrow and retrieve my previous Get-VM | Measure-VM | Select Meter* command. This time, I add the VMName to the output so I can see both virtual machine name as well as the metering duration.

10:43 C:\> get-vm -VMName * | measure-vm | select vmname, meter*

 VMName                                     MeteringDuration

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

sql1                                       00:00:06.4740000

DC1                                        00:00:07.0280000

C2                                         00:00:07.3940000

c1                                         00:00:07.6050000

JJ, that is all there is to using Windows PowerShell to reset Hyper-V Resource Metering counters. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

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: Change the Startup of Your Hyper-V Virtual Machine

$
0
0

Summary: Learn how to use Windows PowerShell 3.0 on Windows 8 to change the startup order of your Hyper-V virtual machine.

Hey, Scripting Guy! Question How can I change the startup order of my virtual machine on my laptop running Windows 8?

Hey, Scripting Guy! Answer You can verify the startup order of your virtual machine by piping the results of Get-VM to the Get-VMBios cmdlet, as shown here.

08:11 C:\> get-vm c2 | Get-VMBios

VMName StartupOrder                            NumLockEnabled

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

C2     {CD, IDE, LegacyNetworkAdapter, Floppy} False

To change the startup order, pipe the results to the Set-VMBios and supply the order as an array. The following illustrates the technique.

08:12 C:\> get-vm c2 |

  Set-VMBios -StartupOrder @("IDE","LegacyNetworkAdapter","CD","Floppy")

08:13 C:\> get-vm c2 | Get-VMBios

 

VMName StartupOrder                            NumLockEnabled

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

C2     {IDE, LegacyNetworkAdapter, CD, Floppy} False

PowerShell Workflows: Using Parameters

$
0
0

Summary: Honorary Scripting Guy and Microsoft PowerShell MVP Richard Siddaway continues his Windows PowerShell workflow series with a discussion on parameters.

Microsoft Scripting Guy, Ed Wilson, is here. Today, we have the sixth in a series of guest blog posts written by Windows PowerShell MVP and Honorary Scripting Guy Richard Siddaway dealing with Windows PowerShell workflow.

Note The first article, PowerShell Workflows: The Basics, introduced the basic concepts of Windows PowerShell workflow. The second article, PowerShell Workflows: Restrictions, discussed the restrictions encountered with working with Windows PowerShell workflows. The third article was PowerShell Workflows: Nesting. The fourth article talked about PowerShell Workflows: Job Engine. The fifth article talked about PowerShell Workflows: Restarting the Computer. You should read those articles prior to reading today’s article.

Richard has written a number of guest Hey, Scripting Guy! Blog posts, and he has also written two books on Windows PowerShell. His most recent book, PowerShell in Depth, is co-written with fellow MVPs Don Jones and Jeffrey Hicks.

Now, take it away, Richard …

In this installment, we’ll look at the parameters that are available to workflows and activities, the options for connecting to remote computers and the workflow cmdlets. Let’s start with the parameters.

There are a good number of parameters available to use with your workflows and activities that are summarized in the following table.

Parameter

Workflow

Activity

AppendOutput

 

Y

AsJob

Y

 

JobName

Y

 

Debug

 

Y

DisplayName

 

Y

ErrorAction

 

Y

Input

 

Y

MergeErrorToOutput

 

Y

PSActionRetryCount

 

Y

PSActionRetryIntervalSec

 

Y

PSActionRunningTimeoutSec

 

Y

PSAllowRedirection

Y

Y

PSApplicationName

Y

Y

PSAuthentication

Y

Y

PSAuthenticationLevel

Y

 

PSCertificateThumbprint

Y

Y

PSComputerName

Y

Y

PSConfigurationName

Y

Y

PSConnectionRetryCount   **

Y

Y

PSConnectionRetryIntervalSec   **

Y

Y

PSConnectionURI

Y

Y

PSCredential

Y

Y

PSDebug

 

Y

PSDisableSerialization

 

Y

PSElapsedTimeOutSec

Y

 

PSError

 

Y

PSParameterCollection

Y

 

PSPersist

Y

Y

PSPort

Y

Y

PSPrivateMetaData

Y

 

PSProgress

 

Y

PSProgressMessage

 

Y

PSRemotingBehavior

 

Y

PSRequiredModules

 

Y

PSRunningTimeOutSec

Y

 

PSSessionOption

Y

Y

PSUseSSL

Y

Y

PSVerbose

 

Y

PSWarning

 

Y

Result

 

Y

UseDefaultInput

 

Y

Verbose

 

Y

WarningAction

 

Y

** The documentation implies these parameters can be used on activities but the activities I tested don’t support them. I suspect they are workflow level parameters.

I don’t propose to discuss each one as they are mostly self-explanatory and more details on the individual parameters can be found in two Help files:

about_WorkflowCommonParameters

about_ActivityCommonParameters

Some of the parameters you’ve already seen in action, such as those related to running the workflow as a job.

Remote access in workflows

One of the more interesting parameters is PSComputerName, which is used for connecting to a remote computer. You get a number of options. First option is to access the remote computer at the workflow level.

workflow test-remoteaccess {

 Get-WmiObject -Class Win32_ComputerSystem

}

Notice in this workflow that there is no obvious reference to a computer name. You can then do this:

PS> test-remoteaccess -PSComputerName server02, win732 | select Name, Manufacturer, Model

Name                          Manufacturer                  Model                      

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

SERVER02                      LENOVO                        4318CTO                    

WIN732                        Microsoft Corporation         Virtual Machine      

Using –PSComputerName at the workflow level passes the remote computer names automatically to the activities in the workflow. This is great if you have a simple workflow where you want all of the activities to access a remote computer; however, if you are returning data from multiple computers, it can get a bit messy. Consider this:

workflow test-remoteaccess {

 Get-WmiObject -Class Win32_ComputerSystem |

 Select-Object  -Property Name, Manufacturer, Model

 Get-Process

 Get-Service

}

test-remoteaccess -PSComputerName server02, win732

I received the data in this order.

Data item

First

Second

WMI

Server02

Win732

Process

Server02

Win732

Service

Server02 and Win732 intermingled

The order in which data is returned is not guaranteed, as with any workflow running activities in parallel.

Using the –PSComputerName at the workflow level is probably best kept for situations where you have simple data return requirements, or you are predominantly performing actions against the remote computer with minimal, or no, data returned.

When you use the –PSComputerName parameter, it effectively replaces the –ComputerName on the cmdlet. You don’t get free connectivity! You will also find that you are connecting over the native mechanism used by the cmdlet. If the remote computer doesn’t support that particular mode of connectivity, your workflow will fail for that computer. You can see an example of this by changing the workflow to use Get-CimInstance instead of Get-WmiObject. You will also need to change the parameter from –Classto –ClassName.  

workflow test-remoteaccess {

 Get-CimInstance -ClassName Win32_ComputerSystem

Let’s run it against the same two computers.

PS> test-remoteaccess -PSComputerName server02, win732

Name             PrimaryOwnerName Domain      TotalPhysicalMemory Model       Manufacture PSComputerName

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

SERVER02         Windows ... Manticor... 17108062208 4318CTO     LENOVO      server02  

The WS-Management service cannot process the request. A DMTF resource URI was used to

access a non-DMTF class. Try again using a non-DMTF resource URI.

    + CategoryInfo          : NotSpecified: (root\cimv2:Win32_ComputerSystem:String) []

   , CimException

    + FullyQualifiedErrorId : HRESULT 0x80338139,Microsoft.Management.Infrastructure.Ci

   mCmdlets.GetCimInstanceCommand

    + PSComputerName        : [localhost]

Server02 works fine, but Win732 fails with a message showing that there is a problem with connectivity through WSMan (WnRM). The WMI cmdlets use DCOM to access remote computers, but the CIM cmdlets use WSMan and it has to be WSMan 3.0 that ships with Windows PowerShell 3.0. Win732 is a computer running Windows 7 with Windows PowerShell 2.0. The resolution is to upgrade the remote computer to Windows PowerShell 3.0, use the WMI cmdlets, or create a CIM session using DCOM (but that’s a subject for another day).

Returning to how you can access a remote computer … you can move the –PSComputerName parameter on to the activity:

workflow test-remoteaccess {

 param(

  [string[]]$computername

 )

 foreach -parallel ($computer in $computername) {

   Get-WmiObject -Class Win32_ComputerSystem -PSComputerName $computer

 }

}

This workflow defines a parameter that takes a list of computer names. The foreach –parallel construct is used to iterate over the computer names. If you remember back to article one in the series, the computers in the list are processed in parallel and the commands within the foreach –parallel block are processed sequentially for each computer. You are back to using the native connectivity (DCOM in this case), so it works like this:

PS> test-remoteaccess -computername server02, win732 | select Name, Manufacturer, Model

Name                          Manufacturer                  Model                      

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

SERVER02                      LENOVO                        4318CTO                    

WIN732                        Microsoft Corporation         Virtual Machine  

You need to consider one last scenario—running a workflow with an InlineScript block where the cmdlets in the block need to connect to remote computers. The big thing for you to remember in this scenario is that you are running cmdlets not workflow activities, so you need to use the cmdlet’s native parameter -ComputerName

workflow test-remoteaccess {

 param(

  [string[]]$computername

 )

 inlinescript {

  foreach ($computer in $using:computername) {

   Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computer

  }

 }

The workflow has a computername parameter that takes a list of computer names. Within the InlineScript block, a foreach loop iterates over the list of computers. You have to define the foreach loop like this:

  foreach ($computer in $using:computername)

The $using modifier enables the loop to access the variable that was defined in a higher scope within the workflow (refer to the second article in the series for more details on variable scope in workflows). The workflow is used in the same as previously.

PS> test-remoteaccess -computername server02, win732 | select Name, Manufacturer, Model

Name                          Manufacturer                  Model                      

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

SERVER02                      LENOVO                        4318CTO                    

WIN732                        Microsoft Corporation         Virtual Machine  

You have seen that there are a number of ways of working with computer names in workflows. There is one more way of doing this, but before looking at that you need to know a bit about the workflow cmdlets.

Workflow cmdlets

The PSWorkflow module has been mentioned a number of times already. It installs two cmdlets in addition to the workflow about* files and the ability to run workflows. There is a second module PSWorkflowUtility that installs a single cmdlet—Invoke-AsWorkflow—which you will see in action in a while. The cmdlets and modules are summarized in the following table.

Module

Cmdlet/Function

PSWorkflow

New-PSWorkflowExecutionOption New-PSWorkflowSession

PSWorkflowUtility

Invoke-AsWorkflow

The cmdlets in the PSWorkflow module are concerned with workflow sessions. You can think of workflow sessions as being analogous to remoting sessions that you’ve known and loved since Windows PowerShell 2.0. If you are running one or two commands against a remote computer, it is probably as efficient to create individual connections and tear them down each time you want to connect. If you are performing many actions against the remote computer each of which would need to create and then destroy a connection you will find it more efficient to create a session to the remote computer.   

The Help file for New-PSWorkflowSession states: “The New-PSWorkflowSession cmdlet creates a user-managed session ("PSSession") that is especially designed for running Windows PowerShell workflows. It uses the Microsoft.PowerShell.Workflow session configuration, which includes scripts, type and formatting files, and options that are required for workflows.” The New-PSWorkflowExecutionOption allows you to further configure and constrain the workflow session, if you require.

If you have ever created a session for Windows PowerShell remoting, you will not have any surprises when it comes to creating a workflow session.

$wkfsess1 = New-PSWorkflowSession -ComputerName server02, win732

$wkfsess1

$sb ={

Import-Module PSWorkflow

workflow test-remoteaccess {

 Get-WmiObject -Class Win32_ComputerSystem |

 select -Property Name, Manufacturer, Model

}

test-remoteaccess

}

Invoke-Command -Session $wkfsess1 -ScriptBlock $sb

The commands you want to run over the session are put into a script block and Invoke-Command is used to run the commands over the session.

Invoke-Command -Session $wkfsess1 -ScriptBlock $sb

New-PSSession : [win732] Connecting to remote server win732 failed with the following error

message : The WS-Management service cannot process the request. Cannot find the

Microsoft.PowerShell.Workflow session configuration in the WSMan: drive on the win732 computer.

For more information, see the about_Remote_Troubleshooting Help topic.

At C:\Windows\system32\WindowsPowerShell\v1.0\Modules\PSWorkflow\PSWorkflow.psm1:58 char:9

+         New-PSSession -ConfigurationName Microsoft.PowerShell.Workflow @PSBoundP ...

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-

   PSSession], PSRemotingTransportException

    + FullyQualifiedErrorId : InvalidResourceUri,PSSessionOpenFailed

 

 Id Name            ComputerName    State         ConfigurationName     Availability

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

  5 Session5        server02        Opened        Microsoft.PowerSh...     Available

WARNING: [localhost]:This workflow job cannot be suspended because there are no persistence points

in the workflow. To make the workflow job suspendable, add persistence points to the workflow.

For more information, see the Help topics for Windows PowerShell Workflows.

Name                  : SERVER02

Manufacturer          : LENOVO

Model                 : 4318CTO

PSSourceJobInstanceId : 78ab3c45-a8f6-428d-a4a4-92aff9df257d

PSComputerName        : server02

RunspaceId            : 6595de20-5cc3-41fa-9cb7-da0f40f1f0e0

Oops. This is the one drawback to using workflow sessions—they are only available if you have Windows PowerShell 3.0 on the remote computer. If you examine the remoting endpoints on a computer running Windows Server 2012 … it has Windows PowerShell 3.0 (WSMAN v3) installed and you will see this:

PS> ls WSMan:\localhost\Plugin | select name

Name                                                                                             

----                                                                                              

Event Forwarding Plugin                                                                          

microsoft.powershell                                                                              

microsoft.powershell.workflow                                                                    

microsoft.powershell32                                                                           

microsoft.windows.servermanagerworkflows                                                         

SEL Plugin                                                                                       

WMI Provider  

By contrast, a computer running Windows 7 with Windows PowerShell 2.0 (WSMAN v2) will show this list of endpoints:

PS> ls WSMan:\localhost\Plugin | select name

Name

----

Event Forwarding Plugin

microsoft.powershell

WMI Provider

You can’t get around this, unfortunately. You have to revert to using the ComputerName or PSComputerName parameters, as discussed earlier.

The last cmdlet is Invoke-AsWorkflow. This is great for testing existing code through a workflow. Start with a simple script:

$exp = "Get-WmiObject -Class Win32_ComputerSystem |

 select -Property Name, Manufacturer, Model"

 You can run it as workflow like this:

Invoke-AsWorkflow -Expression $exp -PSComputerName server02, win732

Before you start thinking this is a shortcut to converting everything to workflows, you need to be aware that it’s not a full answer as Invoke-AsWorkflow takes the expression and runs it as an InlineScript block. You don’t get any of the parallelism—that is one of the great benefits of workflows.

Summary

This article has shown you the range of parameters available to workflows and how they can be used at the workflow or activity level. You have seen that computer names can be supplied to the workflow, an activity, or a workflow session. There is also a way to start testing code in a workflow scenario by using Invoke-AsWorkflow.

The next article in the series will look at some best practices around using workflows and some of the things you need to consider when designing workflows.

Until then, enjoy!

Thank you, Richard.

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: Finding Workflow Help on PowerShell

$
0
0

Summary: Learn how to find help on workflows with Windows PowerShell.

Hey, Scripting Guy! Question I open the Windows PowerShell console and type Get-Help -Categoryhelpfile workflow and nothing returns. How can I fix this problem?

Hey, Scripting Guy! Answer Assuming you have updated your Help file content by using Update-Help, the problem is that you have not loaded the module that contains your cmdlets. The following illustrates Help before loading the modules:

07:45 C:\> help -Category helpfile workflow

about_Modules                     HelpFile                            Explains ho...

about_Object_Creation             HelpFile                            Explains ho...

about_Remote_FAQ                  HelpFile                            Contains qu...

about_Remote_Requirements         HelpFile                            Describes t...

about_Requires                    HelpFile                            Prevents a ...

about_Reserved_Words              HelpFile                            Lists the r...

about_Session_Configurations      HelpFile                            Describes s...

about_Updatable_Help              HelpFile                            SHORT DESCR...

about_Windows_PowerShell_3.0      HelpFile                            Describes s...

about_Windows_PowerShell_ISE      HelpFile                            Describes t...

The following is a simple command to load all modules:

07:45 C:\> gmo -li | ipmo

The following illustrates the results from Help now:

07:46 C:\> help -Category helpfile workflow

Name                              Category  Module                    Synopsis

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

about_Checkpoint-Workflow         HelpFile                        Describes t...

about_Suspend-Workflow            HelpFile                         Describes t...

about_WorkflowCommonParameters    HelpFile            This topic ...

about_Workflows                  HelpFile                            Provides a ...


Create a Custom Hyper-V Resource Metering Reset Report

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, shows you how to create a custom Hyper-V Resource Metering reset report by using Windows PowerShell 3.0.

Microsoft Scripting Guy, Ed Wilson, is here. Well, I found a pretty cool Pandora app for my Windows RT Surface, and so I am listening to a cool Rolling Stones song as I type this. Actually I am surprised at the quality of the music my little Surface RT is spewing out.

United States FTC disclaimer: The Microsoft Scripting Guys work for the Microsoft Corporation. I have been provided with a Windows Surface RT. In addition, the Microsoft Corporation provides me a salary, health insurance, bonus, U.S. national holidays off, and annual leave. The Microsoft Corporation, however, has not purchased for me the Bluetooth wedge mouse or type cover that I use with my Surface. In addition, the Microsoft Corporation did not buy the Windows Surface RT that the Scripting Wife uses.

Anyway, I am playing around this morning, happy that so far I have no meetings either today or tomorrow. In fact, the week is shaping up tremendously … and the Scripting Wife and I are planning on heading out on Friday night to see our friends perform at a local club tomorrow evening. We generally do not hang out with people who do not do Windows PowerShell, so this will be sort of a different experience.

Working with the virtual machine metering report

The VMMeteringReportForVirtualMachine object does not display the amount of time that has lapsed since the Resource Metering was last reset.

Note  See my Use PowerShell to Reset Hyper-V Resource Metering Blog post from Tuesday for more information about resetting the Resource Metering report.

It dawned on me that the MeteringDuration property contains a TimeSpan object. I confirmed this by piping to Get-Member as shown here.

14:16 C:\> get-vm * | Measure-VM | gm -Name MeteringDuration

TypeName: Microsoft.HyperV.PowerShell.VMMeteringReportForVirtualMachine

Name             MemberType Definition

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

MeteringDuration Property   System.Nullable[timespan] MeteringDuration {get;}

So, I decided to pipe the Get-VM command to the Measure-VM cmdlet and then create a custom object. I named one property TimeSpan, and I cast the MeteringDuration property to a [timespan] object. The code is shown here.

Get-VM -vmname * | Measure-VM |

    select-Object vmname,

     @{LABEL="Timespan";EXPRESSION={[timespan]$_.MeteringDuration}}

When I run the code, the following output is shown.

VMName                                            Timespan                                       

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

sql1                                              02:49:51.1750000                               

DC1                                               02:49:51.1760000                                

C2                                                02:49:51.1530000                               

c1                                                02:49:51.1140000                               

 

The big problem with this output is that I have no idea if the TimeSpan represents 2 days or 2 hours. Well, I guess the 49 would probably be minutes or seconds, and the 1750000 is probably something like ticks, but it would be nice to see the TimeSpan expanded.

Creating a new object with TimeSpan details

So, I decide I want to create a new object that expands the Days, Hours, and Minutes properties from the TimeSpan object. Because I now have a custom object that contains the VMName and a TimeSpan object, it is pretty easy for me to create the desired object. I cannot pipe directly to the New-Object cmdlet, but I can pipe to the Foreach-Object cmdlet.

So, I throw the Foreach-Object cmdlet into the mixture, and in the associated ScriptBlock, I add my New-Object cmdlet. I can specify properties by using a HashTable notation. So first off, I create a property named name, and I assign the value from the VMName property of my previous object. Now I use the TimeSpan property from my previous object, and I directly access the Days, Hours, and Minutes. The last step is to choose the type of object—for this, the psobject type is fine. Here is the code I created.

Get-VM -vmname * | Measure-VM |

    select-Object vmname,

     @{LABEL="Timespan";EXPRESSION={[timespan]$_.MeteringDuration}} |

    Foreach-Object {

       New-Object -Property @{

        Name=$_.vmname;

        Days=$_.TimeSpan.Days;

        Hours=$_.TimeSpan.hours

        Minutes=$_.timespan.minutes} -type psobject

       }

When I run the above code, the output shown here displays in the output pane on my Windows PowerShell ISE.

                    Hours                     Days                  Minutes Name                  

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

                       3                        0                       51 sql1                  

                       3                        0                       51 DC1                   

                       3                        0                       51 C2                    

                       3                        0                       51 c1                    

Hmm, the output is what I want, but the order is all messed up. Oh well, I guess I will need to use Format-Table to fix up the formatting.

Formatting the output

The problem with the previous output is that I wanted the Name of the virtual machine, and then I wanted the Days, Hours, and Minutes to display. I could have just put those properties in order and use the Format-Table, but because I am playing around, I decided to do something better.

One of the seldom used parameters for the Format-Table cmdlet is the GroupBy parameter. Well, did you know I could supply a ScriptBlock for the GroupBy parameter? If you did know that, have you forgotten it? Well, I decided to add a ScriptBlock for the GroupBy parameter. So, I group by Computer Name, but I change the Label to “Time Since Last VM Report” and then I pick up the name of the virtual machine. Here is the code—it is cool!

        Format-table -property days, hours, minutes -AutoSize -GroupBy @{

        Label="Time since last VM Report";

        Expression={$_.name} }

 The output is shown in the image that follows.

Image of command output

The complete Get-VMResourceReportConvertToObjectFormatTable.ps1 is shown here.

get-vm -vmname * | Measure-VM |

    select-Object vmname,

     @{LABEL="Timespan";EXPRESSION={[timespan]$_.MeteringDuration}} |

    Foreach-Object {

       New-Object -Property @{

        Name=$_.vmname;

        Days=$_.TimeSpan.Days;

        Hours=$_.TimeSpan.hours

        Minutes=$_.timespan.minutes} -type psobject

       } |

       Format-table -property days, hours, minutes -AutoSize -GroupBy @{

        Label="Time since last VM Report";

        Expression={$_.name} }

I uploaded the complete script to the Scripting Guys Script Repository. This should make it easy for you to download and play with the code. Hope you have an awesome day.

Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

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: Find Windows Hotfixes Installed After a Certain Date

$
0
0

Summary: Use Windows PowerShell to find hotfixes installed on your laptop running Windows 8 that were installed after a certain date.

Hey, Scripting Guy! Question How can I find Windows hotfixes installed after a certain date on my Windows 8 laptop by using Windows PowerShell?

Hey, Scripting Guy! Answer Use the Get-Hotfix function to return installed hotfixes on your Windows 8 laptop, and pipe the results to the Where-Object cmdlet and filter by the installedon property. The following illustrates this technique (? is an alias for the Where-Object cmdlet).

12:35 C:\> Get-HotFix | ? installedon -gt 1/15/2013

Source        Description      HotFixID      InstalledBy          InstalledOn

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

EDLT          Update           KB2803748     NT AUTHORITY\SYSTEM  1/22/2013 12:00...

Use PowerShell to Create and to Use a New Event Log

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to create and to use a new event log.

Microsoft Scripting Guy, Ed Wilson, is here. Well, it’s the weekend, baby! At least for the Scripting Wife and me. You see, the Scripting Manager gave me today and Monday off as sort of “comp time” because of all the long hours I have been working recently. I said cool, and Teresa said, “I know, let’s go to the beach,” so we are back at the beach. And I am back at the coffee house, sitting near the sand and playing around with Windows PowerShell.

Now, if this sounds familiar, it is. Teresa and I headed to the beach last week and like they say in some cheesy movies, “we’re baaack …” I will admit it is really hard to see if I am taking time off, or if I am “working,” even for me, because the two activities overlap so much. If truth be told, I am sitting here right now working—but hey, it’s all fun—and I would be doing this anyway, even if I was not working, which I am not, because my boss told me to take some time off. Now, I did read about a company recently that would pay for you to take vacation—cool, I thought, but you had to leave your cell phone, laptop, surface, etc. behind. That is not a vacation—that sounds more like torture (at least to me).

Use PowerShell to create my own event log

One of the cool things to do with Windows PowerShell is to create my own event logs. Here, I am talking about an event log that is like one of the traditional event logs (traditional event logs are System, Security, and Application). By using Windows PowerShell, these traditional types of event logs are easy to read, easy to write to, easy to back up, and easy to clear.

Use PowerShell to create an event log

I use the New-EventLog cmdlet to create a new event log. To use this cmdlet, I need three things:

  1. Open the Windows PowerShell console with admin rights—an error occurs when attempting to create a new event log without elevated rights.
  2. I need the name for the log.
  3. I need to specify a source for the events that write to the log.

The following command creates a new traditional event log named ScriptingGuys with a source named scripts

New-EventLog -LogName ScriptingGuys -Source scripts

When the command runs, no output appears to the Windows PowerShell console. To ensure the command actually created a new event log, I use the Get-EventLog cmdlet with the –List parameter. Here is the command and the associated output.

10:06 C:\> Get-EventLog -List

  Max(K) Retain OverflowAction        Entries Log

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

  20,480      0 OverwriteAsNeeded      18,504 Application

  20,480      0 OverwriteAsNeeded           0 HardwareEvents

     512      7 OverwriteOlder              0 Internet Explorer

  20,480      0 OverwriteAsNeeded           0 Key Management Service

  10,240      0 OverwriteAsNeeded           4 Lenovo-Customer Feedback

     512      7 OverwriteOlder              2 Lenovo-Lenovo Patch Utility/Admin

     128      0 OverwriteAsNeeded          30 OAlerts

     512      7 OverwriteOlder              0 ScriptingGuys

                                              Security

  20,480      0 OverwriteAsNeeded      21,437 System

  15,360      0 OverwriteAsNeeded      10,059 Windows PowerShell

Configuring my event log

One of the things I notice when I check the ScriptingGuys event log is that it is set to 512 KB, and it will retain entries for 7 days when it will begin deleting older events. This is not the behavior I want. What I want is for the log to be 64 KB in size and to overwrite as needed. To do this, I would think that I use the Set-EventLog cmdlet—but no, there is not such a thing. The cmdlet is named Limit-EventLog. Looking at the Help, it appears there is only one parameter set. Well, I want to OverWriteAsNeeded, so I guess I also need to set a retention days of 0. I craft the following command, but as you can see, it fails.

10:19 C:\> Limit-EventLog -OverflowAction OverWriteAsNeeded -RetentionDays 0 -Maximum

Size 64KB

Limit-EventLog : Cannot validate argument on parameter 'RetentionDays'. The 0 argument is less than the minimum allowed range of 1. Supply an argument that is greater than or equal to 1 and then try the command again.

At line:1 char:65

+ Limit-EventLog -OverflowAction OverWriteAsNeeded -RetentionDays 0 -MaximumSize

+                                                                 ~

    + CategoryInfo          : InvalidData: (:) [Limit-EventLog], ParameterBindingValidationException

    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell

   .Commands.LimitEventLogCommand

Major bummer. Ok, so I try it without the RetentionDays parameter … and it works.

Limit-EventLog -OverflowAction OverWriteAsNeeded -MaximumSize 64KB -LogName scriptingguys

I now use Get-EventLog to confirm my changes took place … the output below confirms that the command worked properly.

10:23 C:\> Get-EventLog -list | ? log -eq scriptingguys

  Max(K) Retain OverflowAction        Entries Log

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

      64      0 OverwriteAsNeeded           0 ScriptingGuys

I can’t get an event log without entries

Interestingly enough, I cannot get an event log that has no entries in it … at least not yet. Because if I use the Get-EventLog cmdlet to attempt to retrieve the ScriptingGuys event log, an error appears. The command and error are here.

10:23 C:\> Get-EventLog -LogName scriptingguys

Get-EventLog : No matches found

At line:1 char:1

+ Get-EventLog -LogName scriptingguys

+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    + CategoryInfo          : ObjectNotFound: (:) [Get-EventLog], ArgumentException

    + FullyQualifiedErrorId : GetEventLogNoEntriesFound,Microsoft.PowerShell.Comman

   ds.GetEventLogCommand

Writing to the event log

To write to my new event log, I need to specify the following information:

  1. The log name (scriptingguys in my example)
  2. The source (scripting in my case)
  3. EventID (I generally start with 1)
  4. EntryType (Information, Warning, Error)
  5. Message (this is what I want to log)

In this example, I add a new entry to the ScriptingGuys event log.

Write-EventLog -LogName ScriptingGuys -Source scripts -Message "Dude, it works ... COOL!" -EventId 0 -EntryType information

I can now use the Get-EventLog cmdlet to retrieve the event. This is shown here.

10:27 C:\> Get-EventLog -LogName scriptingguys

   Index Time          EntryType   Source                 InstanceID Message

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

       1 Jan 29 10:27  Information scripts                         0 Dude, it wor...

That is all there is to using Windows PowerShell to create and to manage event logs. Join me tomorrow when I will talk about more cool stuff.

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 PowerShell to Add Printers to Windows Server 2012

$
0
0

Summary: Learn how to use a Windows PowerShell function to add a printer to your server running Windows Server 2012.

Hey, Scripting Guy! Question How do I use Windows PowerShell 3.0 to add a printer to my print server running Windows Server 2012?

Hey, Scripting Guy! Answer Use the Add-Printer function. Specify the name of an existing print driver and an existing printer port. The following illustrates this technique:

Add-Printer -Name "My 9pin" -DriverName "Generic IBM Graphics 9pin" -PortName "LPT1:"

Weekend Scripter: Sort Process Names by Length of Name

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, takes some time out to play around with the Format-Wide cmdlet.

Microsoft Scripting Guy, Ed Wilson, is here. Well, the Scripting Wife and I are hanging out on the beach this weekend. Because I have a long weekend (thanks to a way cool Scripting Manager) I feel like it is a holiday or something. Well, what do I like to do when I have a holiday? I enjoy playing around with Windows PowerShell—that’s what. Well, I was reviewing the Formatting Windows PowerShell Output chapter for my forthcoming Windows Windows PowerShell 3.0 First Steps book by Microsoft Press (available now with Pre-Order) and I was reminded about using the Format-Wide cmdlet.

Format-Wide? Dude!

Now, I will be honest, I seldom use the Format-Wide cmdlet—most of the time when I could use it, I simply forget about it. It is not one of my most favorite tools, nor do I find it indispensable. Which means, there is probably some things I have not been doing with it.

Now, if I use the Get-Process cmdlet and pipe the process objects to the Format-Wide cmdlet and choose only process names, the output appears jumbled. This command and output are shown in the figure that follows.

The reason for the jumbled output is the length of process names that spread through the output. Hmmmmm. I wonder if there is any way to sort the process names by length of the name? Would that produce a nicer output?

Well Format-Wide has no length parameter

If I want to organize the output from the Format-Wide cmdlet by length of the process name, I am going to have to sort the process names by length prior to arriving at the Format-Wide cmdlet in the pipeline. Ok.

But the Get-Process cmdlet does not have a length parameter I can use to sort by process name length. Hmm … I guess I will need to add a length property to the process object I want to use. In that way, I can use the Sort-Object cmdlet before entering Format-Wide. Sounds like a plan, so how do I do that?

First use a ScriptBlock with Select-Object

The first thing I need to do is to create a custom object with Select-Object. This technique of using the Select-Object cmdlet to create a custom object is one of my favorite Windows PowerShell tricks. Here I need to get the length of each process name. So, I first pipe the results from Get-Process to the Select-Object cmdlet. I can choose the nameproperty easily enough, but to get the length of the name property I need to first ensure the name is a string, and then call a string property (length). The basic syntax for ensuring the process name is a string and calling the string property length is shown here.

13:57 C:\> (gps)[0].name.tostring().length

6

Sweet, it works. Now I know what I want to do, so all I have to do is to create the code to do this for each of the process names. I decide to use a custom hash table type of syntax to create a synthetic property (this hash table sort of technique works with Format-Table, Format-List, but not Format-Wide as well—it is used to create a custom label and a computed value for a standard property. This technique is shown here to create a custom table output.

14:01 C:\> gps | ft name, @{label="length";Expression={$_.name.tostring().Length}} -auto 

Name                       length

----                       ------

armsvc                          6

audiodg                         7

BtwRSupportService             18

…<Output Truncated>

So, I can simply replace the Format-Table cmdlet with the Sort-Object cmdlet, and I am creating a custom object that meets my needs. Here is the code so far.

Get-Process |

Select-Object name, @{label="length";Expression={$_.name.tostring().Length}}

Put it together, sort and format

Now, all I need to do is sort the output by the length and pipe the results to the Format-Wide cmdlet. Of course, Format-Wide does only one property at a time, so I will lose the length in the process, but that is fine. Here is the command up with which I arrived (gps is an alias for Get-Process, select is an alias for Select-Object, sort is an alias for Sort-Object, and fw is the alias for Format-Wide).

gps |

select name, @{label="length";Expression={$_.name.tostring().Length}} |

sort length |

fw -Property name -Column 5

The following figure shows the command (a one-liner) and the output associated with the command. As you can see, the output is much more aesthetically pleasing.

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: Find Processes That Use A Lot of Virtual Memory

$
0
0

Summary: Learn how to use Windows PowerShell to find processes that use more than 1,000 MB of virtual memory.

Hey, Scripting Guy! Question How can I produce a listing of processes on my computer that use more than 1,000 MB of virtual memory?

Hey, Scripting Guy! Answer Use the Get-Process cmdlet to return a listing of all processes. Then pipe the results to the Where-Object and choose the VM alias property. Finally, send the output to the Format-Wide cmdlet and select the name property.

Note   gps is an alias for Get-Processsort is an alias for Sort-Object? is an alias for Where-Object, and fw is an alias for the Format-Wide cmdlet.

Syntax for Windows PowerShell 3.0:

gps | sort vm | ? vm -gt 1000Mb | fw name

Syntax for Windows PowerShell 1.0 and 2.0:

gps | sort vm | ? {$_.vm -gt 1000Mb} | fw name

 

Weekend Scripter: Create a SendTo Notepad Shortcut

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to create a SendTo Notepad shortcut.

Microsoft Scripting Guy, Ed Wilson, is here. I absolutely love using Windows 8. To me, it is the best operating system we have ever released at Microsoft. I am especially proud that some of the Help articles I wrote are actually included with Windows PowerShell Help—it is so cool!

Anyway, one of my favorite things to do is to have a shortcut to Notepad in the SendTo special folder. This way, I can open and look at a lot of things without having to change file associations. I simply right-click, and select Notepad from the SendTo menu. In Windows 8, this is not a default location.

In the following image, I right-click the CreatePoshOrgPro… script, and point to Send to, but Notepad.exe is not listed as a default location to send items.

Image of file directory

Finding the SendTo folder

Ok, so I know that SendTo is a special folder. I guess I can open my user profile folder, find the SendTo folder and create a shortcut to Notepad there—I have done this literally dozens of times over the past few years. But when I attempt to do this, I get access denied. On closer inspection, the SendTo folder is not a real folder, but it redirects to another location.

Image of Windows Explorer

Hmm … So I squirrel around trying to find where we hid the SendTo folder, and then I was reading over the text of my new Windows PowerShell 3.0 Step by Step book by Microsoft Press, and I ran across the section where I talked about using the old-fashioned WshShell object. It dawned on me that I could use this object to completely solve my problem. To begin with, the WshShell object is a COM object, so I need to create an instance of the object by using New-Object. I store the returned COM object in the $wshshell variable, as shown here.

$wshshell = New-Object -com wscript.shell

When I call the SpecialFolders property, I receive a listing of all the special folders about which the object knows. Here is the syntax I use.

$wshshell.SpecialFolders

The command and the output from the command are shown in the following image.

Image of command output

It is common that many COM objects have an itemmethod. I decide to see if the SpecialFolders collection has one … if it does, I will feed it the specific SendTofolder. As shown here, the command works great.

11:08 C:\> $wshshell.SpecialFolders.Item("sendto")

C:\Users\ed.IAMMRED\AppData\Roaming\Microsoft\Windows\SendTo

So I have the path to the SendTo folder …

I paste the path from the $wshshell.SpecialFolders.Item("sendto") command to the Windows Explorer path bar, and sure enough the SendTo folder opens. While I am there, I decide to delete a few things I never use.

I could go ahead and create a new shortcut here, but, dude, that would be like using the GUI and would be the first step to becoming a button monkey … somehow I cannot see myself doing that.

The SendTo folder is shown in the following image.

Image of SendTo folder

Hey, I bet I can script it …

Well, it did not take much time to knock off a quick script. The first thing I need to do is to create the WshShell object and get the path to the SendTo folder—I had already written that code.

$wshshell = New-Object -com wscript.shell

$path = $wshshell.SpecialFolders.Item("sendto")

Next, I need to create a path to use for the shortcut. I like to use Join-Path to create paths because it reduces possible concatenation errors.

$shortcutPath = Join-Path -Path $path -ChildPath "Notepad.lnk"

Now, I need to call the CreateShort method and pass the path for the shortcut. I have to store the returned object, because I need to specify a couple of properties. I put the object in the $shortcut variable.

$shortcut = $wshshell.CreateShortcut($shortcutPath)

Now, I need to specify the target—because Notepad is a well-known application I can avoid specifying the full path to the file. The description is not a requirement, but I like to fill out descriptions when they are available.

$shortcut.TargetPath = "Notepad.exe"

$shortcut.Description = "Created by Powershell 3.0"


Finally, I need to save my work and create the shortcut.

$shortcut.Save()

I mouse over to the SendTo folder, and cool it worked!

Image of Properties folder

CreateNotePadShortCutInSendTo.ps1

$wshshell = New-Object -com wscript.shell

$path = $wshshell.SpecialFolders.Item("sendto")

$shortcutPath = Join-Path -Path $path -ChildPath "Notepad.lnk"

$shortcut = $wshshell.CreateShortcut($shortcutPath)

$shortcut.TargetPath = "Notepad.exe"

$shortcut.Description = "Created by Powershell 3.0"

$shortcut.Save()

I uploaded the complete CreateNotePadShortCutInSendTo.ps1 script to the Scripting Guys Script Repository to make it easy for you to use the code.

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: Find All of the Common Approved PowerShell Verbs

$
0
0

Summary: Learn how to find all of the approved Windows PowerShell verbs that are in the Common group.

Hey, Scripting Guy! Question I want to produce a list of all approved common Windows PowerShell verbs. How do I do it?

Hey, Scripting Guy! Answer This answer comes from my new Windows PowerShell 3.0 Step by Step Microsoft Press book.

Use Get-Verb and pipe the results to the Where-Object cmdlet. Match the group property with the word “common” and send the results to Format-Wide. The command is shown here.

Get-Verb | where group -match 'common' | Format-Wide verb -auto

The command and associated output from the command are shown here.

11:09 C:\> Get-Verb | where group -match 'common' | Format-Wide verb -auto

Add       Clear     Close     Copy      Enter    Exit     Find     Format   Get

Hide      Join      Lock      Move      New      Open     Optimize Pop      Push

Redo      Remove    Rename    Reset     Resize   Search   Select   Set      Show

Skip      Split     Step      Switch    Undo     Unlock   Watch

Use PowerShell to Prepare for a Domain Upgrade

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to obtain operating system version information from domain controllers.

Microsoft Scripting Guy, Ed Wilson, is here. The weather in Charlotte, North Carolina, has been a bit strange of late. There were tornados in Georgia recently, and the temperatures around here rose to 70 degrees Fahrenheit (21 degrees Celsius). It was so warm, the Scripting Wife and I opened the windows and turned off the heat. Well, today, it’s like 35 degrees Fahrenheit (1.6 degrees Celsius), and I do not have the windows open. But I am sitting on the lanai, sipping a nice cup of hot tea (Darjeeling with a spoonful of green tea, a ½ spoonful of Constant Comment, a spoonful of lemon grass, and a pinch of rose buds, hibiscus flower, and lavender—I know I got carried away experimenting, but the results are really quite nice).  

I have my Surface RT with me, and I am checking my email. Actually, around our house, the Scripting Wife and I always have our Surface RTs with us. They follow us up and down the stairs like forlorn puppies as they constantly clamor for attention. Because the Scripting Manager gave me today off, I am being rather mellow this morning. I will probably finish writing my new Microsoft Press Windows PowerShell 3.0 First Steps book, and then take the Scripting Wife out for lunch and a movie. Seems like a cool thing to do, and we have not seen a movie in a while.

AD DS domain mode

Ok, I would like to upgrade my domain functional level to the Windows Server 2012 domain functional level, and then I can set the forest functional level to Windows Server 2012 as well. I was reading a most excellent TechNet Library article, Understanding Active Directory Domain Services (AD DS) Functional Levels, which explains the different functional levels and enumerates what new features each provides.

The first thing I need to do is to find out the functional level of both the forest and the domain. Unfortunately, there is not a Get-ADDomainMode cmdlet or a Get-ADForestMode cmdlet. But, hey, I do not really need them, because I can find the domain level and the forest level from the Get-ADDomain and the Get-ADForest cmdlets, as shown here.

14:36 C:\> (Get-ADForest).ForestMode

Windows2008Forest

14:36 C:\> (Get-ADDomain).DomainMode

Windows2008Domain

To upgrade the domain and forest functional levels

To upgrade the domain functional level and the forest functional level to Windows Server 2012, I need to upgrade all of my domain controllers to Windows Server 2012. To do that, I need to first see where my domain controllers reside, and what version of the operating system they run. I can use the Get-ADComputer cmdlet from the ActiveDirectory module to find all of my domain controllers.

This is actually rather easy because domain controllers reside in the Domain Controllers organizational unit (OU) by default (and it is not a good idea to move Domain Controllers to a different OU without a lot of testing first).

So, I know that my domain controllers reside in the Domain Controllers OU. I can enumerate them by using the Get-ADComputer cmdlet and specifying the search base.

Get-ADComputer -SearchBase "ou=domain controllers,dc=Nwtraders,dc=msft" -Filter *

Ok, that is a good start. But, the output does not include the OperatingSystem information. A sample of the type of information returned is shown here.

DistinguishedName : CN=DC3,OU=Domain Controllers,DC=Nwtraders,DC=msft

DNSHostName       : DC3.Nwtraders.msft

Enabled           : True

Name              : DC3

ObjectClass       : computer

ObjectGUID        : f65af94d-7d7a-49b7-b7cc-120a0ce5c969

SamAccountName    : DC3$

SID               : S-1-5-21-1457956834-3844189528-3541350385-1132

UserPrincipalName :

To add the OperatingSystem version information, I need to add the OperatingSystem attribute to the –propertiesparameter. The revised command is shown here.

Get-ADComputer -SearchBase "ou=domain controllers,dc=iammred,dc=net" -Filter * -Properties operatingsystem

I can now create a table of the required information by piping the output to the Format-Table cmdlet, as shown here.

15:23 C:\> Get-ADComputer -SearchBase "ou=domain controllers,dc=iammred,dc=net" -Filter * -Properties operatingsystem | Format-Table name, operatingsystem -auto

name operatingsystem

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

DC4  Windows Server 2012 Standard

DC2  Windows Server 2012 Standard

DC1  Windows Server® 2008 Enterprise without Hyper-V

DC3  Windows Server 2012 Standard

Ok, that is a bit better, but the operating systems are all jumbled up, and I am particularly interested in the Windows Server 2008 R2 and earlier computers. So, I will sort the output prior to creating the table. Here is the revision.

15:23 C:\> Get-ADComputer -SearchBase "ou=domain controllers,dc=iammred,dc=net" -Filter * -Properties operatingsystem | Sort-Object operatingsystem | Format-Table name, operatingsystem -auto

name operatingsystem

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

DC3  Windows Server 2012 Standard

DC2  Windows Server 2012 Standard

DC4  Windows Server 2012 Standard

DC1  Windows Server® 2008 Enterprise without Hyper-V

Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

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 a PowerShell Cmdlet to Get the Default AD DS Domain Password

$
0
0

Summary: Use a Windows PowerShell cmdlet from the ActiveDirectory module to obtain details about the default AD DS domain password policy.

Hey, Scripting Guy! Question How do I use Windows PowerShell to find the default Active Directory Domain Services (AD DS) domain password policy?

Hey, Scripting Guy! Answer Use the Get-ADDefaultDomainPasswordPolicy cmdlet. No arguments are required. Here is an example:

11:25 C:\>  Get-ADDefaultDomainPasswordPolicy

ComplexityEnabled           : True

DistinguishedName           : DC=nwtraders,DC=msft

LockoutDuration             : 00:30:00

LockoutObservationWindow    : 00:30:00

LockoutThreshold            : 5

MaxPasswordAge              : 42.00:00:00

MinPasswordAge              : 1.00:00:00

MinPasswordLength           : 7

objectClass                 : {domainDNS}

objectGuid                  : 5765f6d1-cb6e-475d-8ed1-0b9ca6abfec1

PasswordHistoryCount        : 24

ReversibleEncryptionEnabled : False

Use PowerShell to Obtain Domain Controller Hardware Info

$
0
0

Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to do a hardware inventory of domain controllers needing an upgrade.

Microsoft Scripting Guy, Ed Wilson, is here. Wow, it seems like a major holiday. The Scripting Wife ordered me some organic spearmint, licorice root, and orange peel from my favorite spice house. I just made myself a pot of tea with a pinch of orange peel, licorice root, English breakfast tea, lemon grass, hibiscus flower, and crushed cinnamon stick. Dude, the stuff is good. Along with just about a half a spoonful of local honey—my Scripting Guys special blend will really wake you up in the morning. Not that I need any waking up today, because I am anxious to get started on writing my script to survey my domain controller hardware in preparation for my domain functional level and forest functional level upgrade.

Note   This is the second part of a series of posts where I talk about upgrading domain and forest functional levels to Windows Server 2012. You really should read yesterday’s post, Use PowerShell to Prepare for a Domain Upgrade, before you are too carried away with today’s post. This is because I am picking up directly with yesterday’s post.

It is just a little bit of WMI

Well, yesterday I talked about querying for domain controllers and returning their current operating system version. If the servers are running Windows Server 2012, there is no need to do a hardware inventory because they are already upgraded. If not, then I need to obtain the hardware info, so I can plan the upgrade. Here is the code I use to determine the operating system version and to decide whether I want to do the WMI query.

Import-Module ActiveDirectory

$dc = Get-ADComputer -SearchBase "ou=domain controllers,dc=iammred,dc=net" -Filter * `

    -Properties operatingsystem

Foreach ($cn in $dc)

 {

  If ($cn.operatingsystem -notmatch '2012')

Now, if the operating system is not Windows Server 2012, I need to query a bunch of WMI classes. This is pretty boring stuff here. I use the Get-WMiObject cmdlet to do the query, and I query five different WMI classes: Win32_Bios, Win32_OperatingSystem, Win32_Processor, Win32_PhysicalMemory, and Win32_Volume. I store each returned object in appropriately named variables. Here is that section of the script.

     $bios = Get-WmiObject -Class win32_bios -ComputerName $cn.name

     $os = Get-WmiObject -class win32_operatingsystem -ComputerName $cn.name

     $processor = Get-WmiObject -Class win32_Processor -ComputerName $cn.name

     $memory = Get-WmiObject -Class win32_physicalmemory -ComputerName $cn.name

     $volume = Get-WmiObject -Class win32_volume -ComputerName $cn.name

Create and return a nice custom object

Ok, so the WMI queries are not too exciting but creating an appropriate custom object is a bit more exciting. I use the New-Object cmdlet to create a custom psobject. I specify the –Property parameter to create the properties on the newly created object. One object for each found domain controller creates. I run each WMI query against my local computer and examine the output. I then select the most useful (for me) properties from each WMI class, and this is what I store in the object. Here is the applicable portion of the script.

         New-Object -TypeName psobject -Property @{

         ComputerName = $cn.DistinguishedName

         biosVersion = $bios.SMBIOSBIOSVersion

         biosMaker = $bios.Manufacturer

         osArchitecture = $os.OSArchitecture

         osName = $os.Caption

         osServicePack = $os.ServicePackMajorVersion

         ProcessorAdddressWidth = $processor.AddressWidth

         ProcessorClock = $processor.MaxClockSpeed

         ProcessorCores = $processor.NumberOfCores

         ProcessorLogical = $processor.NumberOfLogicalProcessors

         ProcessorMake = $processor.Manufacturer

         MemoryCapacity = $memory.capacity

         MemoryBank = $memory.DeviceLocator

         VolumeLetter = $volume.driveLetter

         VolmeFreeSpace = $volume.freespace

         VolumeCapacity = $volume.Capacity }

You know what? This is it. The script uses the technique from yesterday to find all domain controllers and uses Get-WmiObject to query WMI and New-Object to create the custom object. Not too bad.

The following image shows sample output from the script.

Image of command output

To make the script easy for you to use and to modify, I have uploaded it to the Scripting Guys Repository. You can download it from there.

Well, that is all there is to querying Active Directory for domain controllers and performing a hardware inventory. Join me tomorrow when Windows PowerShell MVP and Honorary Scripting Guy Richard Siddaway will return with another installment of his most excellent Windows PowerShell workflow 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 PowerShell to Check Your AD DS Domain Mode

$
0
0

Summary: Use a Windows PowerShell cmdlet from the ActiveDirectory module to check for the domain mode of your AD DS domain.

Hey, Scripting Guy! Question How can I easily find out the domain mode of my Active Directory Domain Services (AD DS) domain by using a Windows PowerShell cmdlet?

Hey, Scripting Guy! Answer Use the Get-ADDomain cmdlet and select the domainMode property. It is also a good idea to select the DistinguishedName at the same time. This technique is shown here.

11:51 C:\> Get-ADDomain | select domainMode, DistinguishedName

                                domainMode DistinguishedName

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

                         Windows2008Domain DC=Nwtraders,DC=Msft

Viewing all 3333 articles
Browse latest View live


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