{"id":65183,"date":"2007-04-02T03:54:00","date_gmt":"2007-04-02T03:54:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2007\/04\/02\/hey-scripting-guy-how-can-i-determine-the-grace-period-for-a-computer-running-windows-vista\/"},"modified":"2007-04-02T03:54:00","modified_gmt":"2007-04-02T03:54:00","slug":"hey-scripting-guy-how-can-i-determine-the-grace-period-for-a-computer-running-windows-vista","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-determine-the-grace-period-for-a-computer-running-windows-vista\/","title":{"rendered":"Hey, Scripting Guy! How Can I Determine the Grace Period for a Computer Running Windows Vista?"},"content":{"rendered":"<p><H2><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"> <\/H2>\n<P>Hey, Scripting Guy! How can I determine the remaining operating system grace period for a computer running Windows Vista?<BR><BR>&#8212; LD<\/P><IMG height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\"><IMG class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\"><\/A> \n<P>Hey, LD. You know, a number of years ago the Scripting Guy who writes this column came outside after work only to discover that his car wouldn\u2019t start. At that time he was working as a sports writer, which occasionally meant working very late at night. This, of course, happened to be one of those occasions: it was 2 o\u2019clock in the morning, no one else was around, and his car wouldn\u2019t start.<\/P>\n<P>To make matters worse, the Scripting Guy who writes this column knows even less about cars than he does about scripting. Not knowing what else to do he opened the hood and took a peek inside. Everything looked fine. although, to tell you the truth, unless something was on fire he wouldn\u2019t know the difference anyway. And even then he might have assumed, \u201cWell, that thing is probably <I>supposed<\/I> to be on fire.\u201d<\/P>\n<P>Feeling the need to do <I>something<\/I> the Scripting Guy jiggled a few wires, closed the hood, and tried starting the car again. Much to his surprise, the car started right up. Not only did he make it home safe and sound that evening, but he never had problems starting the car again. Problem solved!<\/P>\n<P>Now, unlike most of the stories that appear in <I>Hey, Scripting Guy!<\/I> there\u2019s actually a point to this one: sometimes you can fix something even if you don\u2019t have the slightest idea what you\u2019re doing. That\u2019s as true with scripting as it is with cars. After looking under the hood and jiggling a few wires we were able to come up with a way to determine the remaining grace period for Windows product activation; however, we can\u2019t say for sure <I>how<\/I> we came up with that solution, nor can we tell what it all means.<\/P>\n<P>The problem we ran into is that we don\u2019t fully understand Windows Vista licensing. (And yes, we know: we probably <I>are<\/I> the only people in the world who don\u2019t fully understand Windows Vista licensing.) Among other things, Windows Vista has a new feature known as Volume Licensing, feature designed for large enterprises like, well, Microsoft. When we check for licensing and grace period information on our test computer we get back a report that looks like this:<\/P><PRE class=\"codeSample\">Windows Operating System &#8211; Vista, RETAIL channel\nGrace period remaining (hours): 0\nLicensed<\/p>\n<p>Windows Operating System &#8211; Vista, OEM_COA_NSLP channel\nGrace period remaining (hours): 0\nUnlicensed<\/p>\n<p>Windows Operating System &#8211; Vista, OEM_SLP channel\nGrace period remaining (hours): 0\nUnlicensed<\/p>\n<p>Windows Operating System &#8211; Vista, RETAIL channel\nGrace period remaining (hours): 0\nLicensed<\/p>\n<p>Windows Operating System &#8211; Vista, OEM_COA_SLP channel\nGrace period remaining (hours): 0\nUnlicensed\n<\/PRE>\n<P>What does all that mean? Well, to tell you the truth, we aren\u2019t sure. In addition, we aren\u2019t totally sure what the returned data will look like on a Vista machine that <I>doesn\u2019t<\/I> use Volume Licensing. But hey, half of the fun of scripting is simply closing your eyes, running the script, and waiting to see what happens.<\/P>\n<TABLE class=\"dataTable\" id=\"EYD\" cellSpacing=\"0\" cellPadding=\"0\">\n<THEAD><\/THEAD>\n<TBODY>\n<TR class=\"record\" vAlign=\"top\">\n<TD class=\"\">\n<P class=\"lastInCell\"><B>Note<\/B>. Shouldn\u2019t the Scripting Guys make an effort to learn about Volume Licensing, especially in light of the fact that Vista includes a huge new WMI class devoted to software licensing? Yes, we should, and we will. Until that happens, however, you might want to take a few minutes to read up on <A href=\"http:\/\/www.microsoft.com\/technet\/windowsvista\/plan\/faq.mspx\"><B>Volume Licensing<\/B><\/A> and the <A href=\"http:\/\/www.microsoft.com\/technet\/windowsvista\/plan\/volact2.mspx\"><B>SoftwareLicensingProduct<\/B><\/A> class on your own.<\/P><\/TD><\/TR><\/TBODY><\/TABLE>\n<DIV class=\"dataTableBottomMargin\"><\/DIV>\n<P>At any rate, and with no further ado (mainly because we don\u2019t <I>have<\/I> any further ado) here\u2019s a script for determining the remaining grace period on a Windows Vista computer:<\/P><PRE class=\"codeSample\">strComputer = &#8220;.&#8221;<\/p>\n<p>Set objWMIService = GetObject(&#8220;winmgmts:\\\\&#8221; &amp; strComputer &amp; &#8220;\\root\\cimv2&#8221;)<\/p>\n<p>Set colItems = objWMIService.ExecQuery _\n    (&#8220;Select * From SoftwareLicensingProduct&#8221;)<\/p>\n<p>For Each objItem in colItems\n    Wscript.Echo objItem.Description<\/p>\n<p>    intGracePeriod = Int(objItem.GracePeriodRemaining \/ 60)\n    Wscript.Echo &#8220;Grace period remaining (hours): &#8221; &amp; intGracePeriod<\/p>\n<p>    Select Case objItem.LicenseStatus\n        Case 0 Wscript.Echo &#8220;Unlicensed&#8221;\n        Case 1 Wscript.Echo &#8220;Licensed&#8221;\n        Case 2 Wscript.Echo &#8220;Out-Of-Box Grace Period&#8221;\n        Case 3 Wscript.Echo &#8220;Out-Of-Tolerance Grace Period&#8221;\n        Case 4 Wscript.Echo &#8220;Non-Genuine Grace Period&#8221;\n    End Select<\/p>\n<p>    Wscript.Echo\nNext\n<\/PRE>\n<P>OK, let\u2019s see if we can at least <I>kind<\/I> of figure out what\u2019s going on here. As you can see, we start out by connecting to the WMI service on the local computer (although this script works equally well against remote computers). We then use this line of code to retrieve all the instances of the SoftwareLicensingProduct class 9which, in case you\u2019re wondering, replaces the Win32_WindowsProductActivation class found in Windows XP and Windows Server 2003:<\/P><PRE class=\"codeSample\">Set colItems = objWMIService.ExecQuery _\n    (&#8220;Select * From SoftwareLicensingProduct&#8221;)\n<\/PRE>\n<P>OK, so maybe that part <I>was<\/I> pretty easy, wasn\u2019t it? After issuing the query we then set up a For Each loop to walk through all the items in the returned collection. Inside that loop, the very first thing we do is echo back the value of the <B>Description<\/B> property:<\/P><PRE class=\"codeSample\">Wscript.Echo &#8220;Description: &#8221; &amp; objItem.Description\n<\/PRE>\n<P>Still pretty easy, isn\u2019t it? OK, let\u2019s take a look at the <B>GracePeriodRemaining<\/B> property. As it turns out, this property tells you the remaining time (in minutes) before the grace period expires. (Or, on Volume Licensing clients, the remaining time, again in minutes, before re-activation is required.) Just for the heck of it, we grab the value of this property and then divide it by 60; that allows us to express the remaining grace period in hours:<\/P><PRE class=\"codeSample\">intGracePeriod = Int(objItem.GracePeriodRemaining \/ 60)\nWscript.Echo &#8220;Grace period remaining (hours): &#8221; &amp; intGracePeriod\n<\/PRE>\n<P>Would you rather have this value expressed in days? No problem; just divide by 1440 instead (60 minutes in an hour times 24 hours in a day yields 1440 minutes in a day):<\/P><PRE class=\"codeSample\">intGracePeriod = Int(objItem.GracePeriodRemaining \/ 1440)\nWscript.Echo &#8220;Grace period remaining (hours): &#8221; &amp; intGracePeriod\n<\/PRE>\n<P>That\u2019s actually all LD asked for, but we decided to go one step further and report back the license status as well. To do that we simply use a Select Case statement that takes action based on the value of the <B>LicenseStatus<\/B> property:<\/P><PRE class=\"codeSample\">Select Case objItem.LicenseStatus\n    Case 0 Wscript.Echo &#8220;Unlicensed&#8221;\n    Case 1 Wscript.Echo &#8220;Licensed&#8221;\n    Case 2 Wscript.Echo &#8220;Out-of-Box Grace Period&#8221;\n    Case 3 Wscript.Echo &#8220;Out-of-Tolerance Grace Period&#8221;\n    Case 4 Wscript.Echo &#8220;Non-Genuine Grace Period&#8221;\nEnd Select\n<\/PRE>\n<P>Again, the code itself isn\u2019t very complicated. LicenseStatus returns a value of 0, 1, 2, 3, or 4. All we do is take a look at this value and then echo back the actual license status. For example, if LicenseStatus equals 2 that means that the operating system is in the Out-of-Box Grace period. Fittingly enough, we then echo back that very fact:<\/P><PRE class=\"codeSample\">Case 2 Wscript.Echo &#8220;Out-of-Box Grace Period&#8221;\n<\/PRE>\n<P>So what exactly does it mean to be in the Out-of-Box Grace period, and what are the implications of that? Well, that\u2019s the problem: we don\u2019t really know. But with any luck you can find the answers <A href=\"http:\/\/www.microsoft.com\/technet\/windowsvista\/plan\/volact2.mspx\"><B>here<\/B><\/A>.<\/P>\n<P>We hope that this points you in the right direction, LD. As soon as we get home tonight we\u2019ll start digging a little deeper into Vista licensing. <\/P>\n<P>Well, assuming we get the car started and can actually <I>get<\/I> home, that is. Hmmm, wonder if anything bad would happen if we jiggled this wi&#8211;<\/P>\n<DIV><A href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr07\/hey0402.mspx#top\"><IMG height=\"9\" alt=\"Top of page\" src=\"http:\/\/www.microsoft.com\/library\/gallery\/templates\/MNP2.Common\/images\/arrow_px_up.gif\" width=\"7\" border=\"0\"><\/A><A class=\"topOfPage\" href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/apr07\/hey0402.mspx#top\">Top of page<\/A><\/DIV><A class=\"\" title=\"ECG\" name=\"ECG\"><\/A>\n<H2>Determining the Grace Period Using Windows PowerShell<\/H2>\n<P>We can\u2019t promise to do this every day, but whenever possible we\u2019ll try to provide a Windows PowerShell solution along with the VBScript solutions typically used in the <I>Hey, Scripting Guy!<\/I> column. Here\u2019s a sample solution from PowerShell pro June Blender.<\/P>\n<P>I knew that I this task could be done easily in Windows PowerShell, because PowerShell can access any WMI class. (There are a few caveats, but I don&#8217;t think this one qualifies.) And the Scripting Guy did all of the heavy lifting: he determined which WMI class to use and found interesting properties to display.<\/P>\n<P>Here&#8217;s a simple Windows PowerShell command that displays the grace period for Windows Vista license:<\/P><PRE class=\"codeSample\">get-wmiobject -class SoftwareLicensingProduct | format-List -property Name, Description, &#8216;GracePeriodRemaining, LicenseStatus\n<\/PRE>\n<P>Here&#8217;s a more complex version that calculates the grace period in days, instead of minutes, and translates the LicenseStatus property integer values to their meanings:<\/P><PRE class=\"codeSample\">$L = get-wmiobject -class SoftwareLicensingProduct\n$L | format-list -property Name, Description, `\n             @{Label=&#8221;Grace period (days)&#8221;; Expression={ $_.graceperiodremaining \/ 1440}}, `\n             @{Label= &#8220;License Status&#8221;; Expression={switch (foreach {$_.LicenseStatus}) `\n              { 0 {&#8220;Unlicensed&#8221;} `\n                1 {&#8220;Licensed&#8221;} `\n                2 {&#8220;Out-Of-Box Grace Period&#8221;} `\n                3 {&#8220;Out-Of-Tolerance Grace Period&#8221;} `\n                4 {&#8220;Non-Genuine Grace Period&#8221;} `\n              } } }\n<\/PRE>\n<P>Here&#8217;s the output. It&#8217;s not exactly like the VBScript output, but it will do:<\/P><PRE class=\"codeSample\">Name                : Windows(TM) Vista, Enterprise edition\nDescription         : Windows Operating System &#8211; Vista, VOLUME_KMS channel\nGrace period (days) : 0\nLicense Status      : Unlicensed<\/p>\n<p>Name                : Windows(TM) Vista, Enterprise edition\nDescription         : Windows Operating System &#8211; Vista, VOLUME_MAK channel\nGrace period (days) : 0\nLicense Status      : Unlicensed<\/p>\n<p>Name                : Windows(TM) Vista, OCUR add-on for Ultimate,HomePremium\nDescription         : Windows Operating System &#8211; Vista, RETAIL channel\nGrace period (days) : 0\nLicense Status      : Unlicensed<\/p>\n<p>Name                : Windows(TM) Vista, Enterprise edition\nDescription         : Windows Operating System &#8211; Vista, RETAIL channel\nGrace period (days) : 0\nLicense Status      : Unlicensed<\/p>\n<p>Name                : Windows(TM) Vista, Enterprise edition\nDescription         : Windows Operating System &#8211; Vista, VOLUME_KMSCLIENT channe\n                      l\nGrace period (days) : 173.5\nLicense Status      : Licensed<\/p>\n<p>Name                : Windows(TM) Vista, Enterprise edition\nDescription         : Windows Operating System &#8211; Vista, OEM_SLP channel\nGrace period (days) : 0\nLicense Status      : Unlicensed\n<\/PRE>\n<P>Windows PowerShell makes this otherwise complex task rather easy. The Get-WmiObject cmdlet has a Class parameter (-class) that lets you specify any WMI class. The Scripting Guy told us to use the SoftwareLicensingProduct class, and we always do what he says. I saved the output in a variable named $L (for &#8220;license&#8221;):<\/P><PRE class=\"codeSample\">$L = get-wmiobject -class SoftwareLicensingProduct\n<\/PRE>\n<P>At this point we have all of the data that we need in the $L variable; all that&#8217;s left to do is to format the output. I chose to format the data as a list, because the long values would be truncated in a table. <\/P>\n<P>The Format-List cmdlet has a Property parameter (-property) that lets you select the properties that are displayed in the list. And I copied the properties that the Scripting Guy used in his script:<\/P><PRE class=\"codeSample\">format-List -property Name, Description, GracePeriodRemaining, LicenseStatus\n<\/PRE>\n<P>This command is designed to find the grace period on my local computer, but I could easily add the ComputerName parameter of Get-WmiObject to run the same command on a remote computer, such as one named Vista2.<\/P><PRE class=\"codeSample\">get-wmiobject -class SoftwareLicensingProduct -computername Vista2 | format-List Name, Description, GracePeriodRemaining, LicenseStatus\n<\/PRE>\n<P>I&#8217;m done with the task, but I&#8217;m still curious about this new SoftwareLicensingProduct object. Perhaps, just perhaps, the Scripting Guy didn&#8217;t show all of the cool properties of the class. Or, maybe the objects in this class have methods that I might want to use later. <\/P>\n<P>Because I have objects, not just strings, I don&#8217;t need to retrieve the data again; I just need to re-format the display. First, I&#8217;ll look at the properties that we didn&#8217;t use in this display.<\/P>\n<P>I can easily view all of the properties and methods of the objects in $L by using the Get-Member cmdlet. In this command, I use a pipeline operator (|) to send the objects in the $L variable to Get-Member:<\/P><PRE class=\"codeSample\">$L | get-member\n<\/PRE>\n<P>And here&#8217;s the result: the properties and methods of a SoftwareLicensingProduct object.<\/P><PRE class=\"codeSample\">TypeName: System.Management.ManagementObject#root\\cimv2\\SoftwareLicensingPro\nduct<\/p>\n<p>Name                         MemberType   Definition\n&#8212;-                         &#8212;&#8212;&#8212;-   &#8212;&#8212;&#8212;-\nActivate                     Method       System.Management.ManagementBaseOb&#8230;\nDepositOfflineConfirmationId Method       System.Management.ManagementBaseOb&#8230;\nUninstallProductKey          Method       System.Management.ManagementBaseOb&#8230;\nApplicationID                Property     System.String ApplicationID {get;s&#8230;\nDescription                  Property     System.String Description {get;set;}\nEvaluationEndDate            Property     System.String EvaluationEndDate {g&#8230;\nGracePeriodRemaining         Property     System.UInt32 GracePeriodRemaining&#8230;\nID                           Property     System.String ID {get;set;}\nLicenseStatus                Property     System.UInt32 LicenseStatus {get;s&#8230;\nMachineURL                   Property     System.String MachineURL {get;set;}\nName                         Property     System.String Name {get;set;}\nOfflineInstallationId        Property     System.String OfflineInstallationI&#8230;\nPartialProductKey            Property     System.String PartialProductKey {g&#8230;\nProcessorURL                 Property     System.String ProcessorURL {get;set;}\nProductKeyID                 Property     System.String ProductKeyID {get;set;}\nProductKeyURL                Property     System.String ProductKeyURL {get;s&#8230;\nUseLicenseURL                Property     System.String UseLicenseURL {get;s&#8230;\n__CLASS                      Property     System.String __CLASS {get;set;}\n__DERIVATION                 Property     System.String[] __DERIVATION {get;&#8230;\n__DYNASTY                    Property     System.String __DYNASTY {get;set;}\n__GENUS                      Property     System.Int32 __GENUS {get;set;}\n__NAMESPACE                  Property     System.String __NAMESPACE {get;set;}\n__PATH                       Property     System.String __PATH {get;set;}\n__PROPERTY_COUNT             Property     System.Int32 __PROPERTY_COUNT {get&#8230;\n__RELPATH                    Property     System.String __RELPATH {get;set;}\n__SERVER                     Property     System.String __SERVER {get;set;}\n__SUPERCLASS                 Property     System.String __SUPERCLASS {get;set;}\nConvertFromDateTime          ScriptMethod System.Object ConvertFromDateTime();\nConvertToDateTime            ScriptMethod System.Object ConvertToDateTime();\nDelete                       ScriptMethod System.Object Delete();\nGetType                      ScriptMethod System.Object GetType();\nPut                          ScriptMethod System.Object Put();\n<\/PRE>\n<P>Hmm, Activate and UninstallProductKey methods. An OfflineInstallationID property. Okay, these are interesting, but I need to see an example. <\/P>\n<P>Because the Get-WmiObject cmdlet retrieved more than one object, I actually have a group or array of objects. I can use the . (that&#8217;s a dot) property operator and the Count property of an array to find out how many objects I have.<\/P><PRE class=\"codeSample\">$L.count\n6\n<\/PRE>\n<P>And I discover that I have six of them; a bit too much for one display.<\/P>\n<P>I&#8217;ll select the most interesting one &#8212; the one with the license &#8212; and display the values of its properties. This command uses the Where-Object cmdlet (alias = &#8220;where&#8221;) to select one of the objects, the one with the word &#8220;client&#8221; somewhere in the description text. Again, I use the Format-List cmdlet and use its Property parameter with a value of <B>all<\/B> (*).<\/P><PRE class=\"codeSample\">$L | where {$_.description -like &#8220;*client*&#8221;} | format-list -property *<\/p>\n<p>__GENUS               : 2\n__CLASS               : SoftwareLicensingProduct\n__SUPERCLASS          :\n__DYNASTY             : SoftwareLicensingProduct\n__RELPATH             : SoftwareLicensingProduct.ID=&#8221;cfd8ff08-c0d7-452b-9f60-ef\n                        5c70c32094&#8243;\n__PROPERTY_COUNT      : 14\n__DERIVATION          : {}\n__SERVER              : JUNEB-TESTV\n__NAMESPACE           : root\\cimv2\n__PATH                : \\\\JUNEB-TESTV\\root\\cimv2:SoftwareLicensingProduct.ID=&#8221;c\n                        fd8ff08-c0d7-452b-9f60-ef5c70c32094&#8243;\nApplicationID         : 55c92734-d682-4d71-983e-d6ec3f16059f\nDescription           : Windows Operating System &#8211; Vista, VOLUME_KMSCLIENT chan\n                        nel\nEvaluationEndDate     : 16010101000000.000000-000\nGracePeriodRemaining  : 249840\nID                    : cfd8ff08-c0d7-452b-9f60-ef5c70c32094\nLicenseStatus         : 1\nMachineURL            : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57203\nName                  : Windows(TM) Vista, Enterprise edition\nOfflineInstallationId : 013421174935129263064954303550341742525985120465630192\nPartialProductKey     : 4BWMV\nProcessorURL          : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57201\nProductKeyID          : 89579-00142-236-020020-03-1033-6000.0000-0292007\nProductKeyURL         : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57204\nUseLicenseURL         : http:\/\/go.microsoft.com\/fwlink\/?LinkId=572\n<\/PRE>\n<P>Now, I can display some of these other properties, just by changing the Format-List command. This time, I&#8217;ll pipe the objects in the $L variable to a Format-List command with a different set of properties:<\/P><PRE class=\"codeSample\">$L | format-List Name, Description, GracePeriodRemaining, LicenseStatus, __SERVER, ProductKeyURL\n<\/PRE>\n<P>Here&#8217;s the result:<\/P><PRE class=\"codeSample\">Name                 : Windows(TM) Vista, Enterprise edition\nDescription          : Windows Operating System &#8211; Vista, VOLUME_KMS channel\nGracePeriodRemaining : 0\nLicenseStatus        : 0\n__SERVER             : JUNEB-TESTV\nProductKeyURL        : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57204<\/p>\n<p>Name                 : Windows(TM) Vista, Enterprise edition\nDescription          : Windows Operating System &#8211; Vista, VOLUME_MAK channel\nGracePeriodRemaining : 0\nLicenseStatus        : 0\n__SERVER             : JUNEB-TESTV\nProductKeyURL        : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57204<\/p>\n<p>Name                 : Windows(TM) Vista, OCUR add-on for Ultimate,HomePremium\nDescription          : Windows Operating System &#8211; Vista, RETAIL channel\nGracePeriodRemaining : 0\nLicenseStatus        : 0\n__SERVER             : JUNEB-TESTV\nProductKeyURL        : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57204<\/p>\n<p>Name                 : Windows(TM) Vista, Enterprise edition\nDescription          : Windows Operating System &#8211; Vista, RETAIL channel\nGracePeriodRemaining : 0\nLicenseStatus        : 0\n__SERVER             : JUNEB-TESTV\nProductKeyURL        : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57204<\/p>\n<p>Name                 : Windows(TM) Vista, Enterprise edition\nDescription          : Windows Operating System &#8211; Vista, VOLUME_KMSCLIENT chann\n                       el\nGracePeriodRemaining : 258900\nLicenseStatus        : 1\n__SERVER             : JUNEB-TESTV\nProductKeyURL        : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57204<\/p>\n<p>Name                 : Windows(TM) Vista, Enterprise edition\nDescription          : Windows Operating System &#8211; Vista, OEM_SLP channel\nGracePeriodRemaining : 0\nLicenseStatus        : 0\n__SERVER             : JUNEB-TESTV\nProductKeyURL        : http:\/\/go.microsoft.com\/fwlink\/?LinkId=57204\n<\/PRE>\n<P>Okay, it&#8217;s not much more useful in this case. Once again, we&#8217;ll have to concede to the Scripting Guy.<\/P>\n<P>One last issue is how I managed the fancy formatting in the second version of the command:<\/P><PRE class=\"codeSample\">$L = get-wmiobject -class SoftwareLicensingProduct\n$L | format-list Name, Description, `\n             @{Label=&#8221;Grace period (days)&#8221;; Expression={ $_.graceperiodremaining \/ 1440}}, `\n             @{Label= &#8220;License Status&#8221;; Expression={switch (foreach {$_.LicenseStatus}) `\n              { 0 {&#8220;Unlicensed&#8221;} `\n                1 {&#8220;Licensed&#8221;} `\n                2 {&#8220;Out-Of-Box Grace Period&#8221;} `\n                3 {&#8220;Out-Of-Tolerance Grace Period&#8221;} `\n                4 {&#8220;Non-Genuine Grace Period&#8221;} `\n              } } }\n<\/PRE>\n<P>To manipulate a property value before displaying it, I used a <I>calculated property<\/I>. This takes the form of a &#8220;hash table,&#8221; (formally called an <I>associative array<\/I><B><\/B>to avoid any hint of impropriety). Each hash table can have Label, Expression, Format, and Alignment keys. You can use them with Select-Object and the formatting cmdlets (Format-*). For examples, see &#8220;get-help format-table -examples&#8221;.<\/P>\n<P>Here&#8217;s the format:<\/P><PRE class=\"codeSample\">@{&lt;key&gt;=&lt;value&gt;; [&lt;key&gt;=&lt;value&gt;\u2026]}\n<\/PRE>\n<P>such as:<\/P><PRE class=\"codeSample\">@{Label=&#8221;Name&#8221;; Expression={$_.Property * Int}}\n<\/PRE>\n<P>(The tricky part is remembering the correct number of parentheses and curly braces\u2026)<\/P>\n<P>In this case, to convert the value of the GracePeriodRemaining property from minutes to days, I divided the value by 1440, the number of minutes in a day. The expression starts with a <B>$_ <\/B>, the symbol that represents the current object. You need it whenever you are displaying more than one object (in this case, 6 of them).<\/P><PRE class=\"codeSample\">@{Label=&#8221; Grace period (days)&#8221;; Expression={$_.graceperiodremaining \/ 1440}}\n<\/PRE>\n<P>To change the integer values of the LicenseStatus properties to meaningful names, I typed a <B>switch<\/B> statement in the value of the Expression key. Windows PowerShell uses a pretty standard form of the <B>switch<\/B> statement. For a detailed description of switch statements in PowerShell, at the Windows PowerShell command prompt, type &#8220;get-help about_switch&#8221;.<\/P>\n<P>These simple commands can be very powerful. Again, the trick was finding the SoftwareLicensingProduct class of WMI. In this case, like many others, I relied on the venerable Scripting Guy, but if he was off at a baseball game &#8212; I mean, occupied in an important meeting &#8212; you can use the List parameter of Get-WmiObject to list all of the available WMI classes.<\/P><PRE class=\"codeSample\">get-wmiobject -list\n<\/PRE>\n<P>I&#8217;ll continue to rely on the Scripting Guy.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! How can I determine the remaining operating system grace period for a computer running Windows Vista?&#8212; LD Hey, LD. You know, a number of years ago the Scripting Guy who writes this column came outside after work only to discover that his car wouldn\u2019t start. At that time he was working as [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[16,47,3,5,725],"class_list":["post-65183","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-desktop-management","tag-general-management-tasks","tag-scripting-guy","tag-vbscript","tag-windows-vista"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! How can I determine the remaining operating system grace period for a computer running Windows Vista?&#8212; LD Hey, LD. You know, a number of years ago the Scripting Guy who writes this column came outside after work only to discover that his car wouldn\u2019t start. At that time he was working as [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/65183","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=65183"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/65183\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=65183"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=65183"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=65183"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}