Monday, February 3, 2014

Powershell: One Liner to output windows services and their StartMode

Here is a one line Powershell command to output the Windows services and their start-up type (Manual, Auto, Disabled).

Handy to check SOE images and ensure all those services are set consistently in between releases or simply take a dump of those settings on servers to keep track of things.

(Get-Service).name | %{@{$_=(Get-WmiObject -Class Win32_Service -Property StartMode -Filter "Name='$_'").StartMode}}




Edit: Here is a more advanced version of that one liner, with the display name and then the service name ( start-up type) - Service Status.
Notice the use of an hash table and -f option to format the output string and include several object properties.

Get-Service |%{@{$_.DisplayName='{0} ({1}) - {2}' -f $_.Name,(Get-WmiObject -Class Win32_Service -Property StartMode -Filter  "Name='$($_.Name)'").StartMode, $_.status}} | format-Table -AutoSize




Friday, January 17, 2014

PowerShell Script: GPO replication status across Domain Controller

Helloooo !!

A colleague asked me to create a PS script to check for a given GPO its AD and Sysvol versions across all Domain Controllers.

So I wrote this script that utilize the ActiveDirectory and GroupPolicy Module.

Depending on the size of your domain it can take a couple of minutes to contact each DC and retrieve the info, so launch it and go for a coffee or something...

In the same fashion as for the script from my last post, we will again be using a system object to collect all of the data together, which gives you the option to pipe it nicely to display the data or create CSV reports.
So here we go:

What the script does: 

This script takes the name of the GPO you want to check the replication status as an argument. 
It then uses the get-addomaincontroller  cmdlet from the ActiveDirectory Module to gather a list of all domain controllers host name to query. 
The retrieval of the versions on each DC is done using the Get-GPO cmdlet with -server option.

All of it is then wacked into a System.Object which is output at the end of the process. 

It is assumed that the ActiveDirectory and GroupPolicy modules are already imported in your session and that you have set the ExecutionPolicy properly on your system beforehand so that you can run the script locally.

How it works: 

Here are a few syntax example to use the script. 

& Get-GPOReplicationReport.ps1 "My GPO Name_v1.5" | Out-GridView
      The script creates a report for the specified GPO and display it in the out.GridView window.

& Get-GPOReplicationReport.ps1 "My GPO Name_v1.5" | ConverTo-Csv -Delimiter ','
      The script creates a report for the specified GPO and display it in the powershell host window as a comma delimited string (for copy and paste) .

& Get-GPOReplicationReport.ps1 "My GPO Name_v1.5" |  Export-Csv -Delimiter ',' -Path C:\MyGPOReplicationReport.csv
      The script creates a report for the specified GPO and save it as a CSV file.

Download Link:


Script Content:

#Created by toussman@gmail.com on 17/01/2014 
#http://theplatformadmin.blogspot.co.uk/

param(
  [parameter(Mandatory = $TRue )][String]$GPOName
 )

$DCList = (get-addomaincontroller -filter *).hostname 

$colGPOVer = @()

foreach ($DC in $DCList){

$objGPOVers = New-Object System.Object

$GPOObj = Get-GPO $GPOName -server $DC

$UserVersion = [string]$GPOObj.User.DSVersion + ' (AD), ' + [string]$GPOObj.User.SysvolVersion + ' (sysvol)'
$ComputerVersion = [string]$GPOObj.Computer.DSVersion + ' (AD), ' + [string]$GPOObj.Computer.SysvolVersion + ' (sysvol)'

$objGPOVers | Add-Member -type noteproperty -name GPOName -value $GPOName
$objGPOVers | Add-Member -type noteproperty -name DCName -value $DC
$objGPOVers | Add-Member -type noteproperty -name UserVersion -value $UserVersion
$objGPOVers | Add-Member -type noteproperty -name ComputerVersion -value $ComputerVersion

$colGPOVer += $objGPOVers 
}

$colGPOVer | sort-object GPOName, DCName

Well, that's it for this post. 

I hope you will find the script useful and if you have any suggestions or spot something that can be improved leave me a comment to let me know. 

Until next time !! 

Thursday, January 16, 2014

PowerShell Script: HouseKeeping GPO Report

Hello there !! 

My first post for 2014 is going to be about a Powershell script I just created to produce a GPO Report to keep track of the environment and also list GPOs for housekeeping tasks such as listing all the GPOs without WMIfilter, all the GPOs linked to a particular OU, ...

None of the GroupPolicy cmdlets that come with the GroupPolicy Module in RSAT actually allowed me to produce an all in one report based on the actual object configuration (i.e.: OU Linked, WMI filter applied, Security filtering, ... ).

It is assumed that you have imported the GroupPolicy module and that you have set the ExecutionPolicy properly on your system beforehand so that you can run the script locally.

What the script does: 

The script gets a specified list or all of the GPO in a domain and returns the following list of properties per GPO and per OU Link:
GPOName, LinksPath, WmiFilter, CreatedTime, ModifiedTime, ComputerRevisionsAD, ComputerRevisionsSYSVOL, UserRevisionsAD, UserRevisionsSYSVOL, ComputerSettingsEnabled, UserSettingsEnabled, SecurityFilter.

In other words if a GPO is linked to more than one OU it will appear once per OU where it is linked in the report. That is the same as the GPMC display tree view.

The report focuses on what is actually in effect on the domain, therefore:
- Links that are not enabled are discarded automatically.
- Security filtering for groups, users and computers that have been deleted from the domain but are still showing as SID in the GPO are skipped and not showing the report.

How it works: 

Here are a few syntax example to use the script. 

& Get-GPOReport.ps1 -All | Out-GridView
      The script creates a report for all the GPOs on the domain.

& Get-GPOReport.ps1 -GPOList  GPOName1,GPOName2,GPOName3 | ConverTo-Csv -Delimiter ','
      The script creates a report for the specified GPO.

$a = Get-Content C:\MyListOfGPOs.txt 
& Get-GPOReport.ps1 -GPOList $a | Export-Csv -Delimiter ',' -Path C:\MyGPOReport.csv
      The script creates a report for the GPOs specified in C:\MyListOfGPOs.txt.

Download Link:

https://drive.google.com/file/d/0B3ED4HUGG162LTNWWGNRaENVWmc/edit?usp=sharing

Script Content:

#Created by toussman@gmail.com on 16/01/2014 
#http://theplatformadmin.blogspot.co.uk/

param(
[parameter(Mandatory = $False )][array]$GPOList,
    [parameter(Mandatory = $False )][switch]$All
)

if( $All ){$GPOList = (Get-Gpo -All).DisplayName}
If( $GPOList -eq $null){Write-Host "Specify a list of GPOs!!"; Break}

$colGPOLinks = @()

foreach ($GPOItem in $GPOList){
       
    [xml]$gpocontent = Get-GPOReport $GPOItem -ReportType xml
    $LinksPaths = $gpocontent.GPO.LinksTo | ?{$_.Enabled -eq $True} | %{$_.SOMPath}
    $Wmi = Get-GPO $GPOItem | Select-Object WmiFilter
    
    $CreatedTime = $gpocontent.GPO.CreatedTime
    $ModifiedTime = $gpocontent.GPO.ModifiedTime
    
    $CompVerDir = $gpocontent.GPO.Computer.VersionDirectory
    $CompVerSys = $gpocontent.GPO.Computer.VersionSysvol
    $CompEnabled = $gpocontent.GPO.Computer.Enabled
    
    $UserVerDir = $gpocontent.GPO.User.VersionDirectory
    $UserVerSys = $gpocontent.GPO.User.VersionSysvol
    $UserEnabled = $gpocontent.GPO.User.Enabled

    $SecurityFilter = ((Get-GPPermissions -Name $GPOItem -All | ?{$_.Permission -eq "GpoApply"}).Trustee | ?{$_.SidType -ne "Unknown"}).name -Join ','

    foreach ($LinksPath in $LinksPaths){
        $objGPOLinks = New-Object System.Object
        $objGPOLinks | Add-Member -type noteproperty -name GPOName -value $GPOItem
        $objGPOLinks | Add-Member -type noteproperty -name LinksPath -value $LinksPath
        $objGPOLinks | Add-Member -type noteproperty -name WmiFilter -value ($wmi.WmiFilter).Name
        $objGPOLinks | Add-Member -type noteproperty -name CreatedTime -value $CreatedTime
        $objGPOLinks | Add-Member -type noteproperty -name ModifiedTime -value $ModifiedTime
        $objGPOLinks | Add-Member -type noteproperty -name ComputerRevisionsAD -value $CompVerDir
        $objGPOLinks | Add-Member -type noteproperty -name ComputerRevisionsSYSVOL -value $CompVerSys
        $objGPOLinks | Add-Member -type noteproperty -name UserRevisionsAD -value $UserVerDir
        $objGPOLinks | Add-Member -type noteproperty -name UserRevisionsSYSVOL -value $UserVerSys
        $objGPOLinks | Add-Member -type noteproperty -name ComputerSettingsEnabled -value $CompEnabled
        $objGPOLinks | Add-Member -type noteproperty -name UserSettingsEnabled -value $UserEnabled
        $objGPOLinks | Add-Member -type noteproperty -name SecurityFilter -value $SecurityFilter

        $colGPOLinks += $objGPOLinks
    }
}

$colGPOLinks | sort-object GPOName, LinksPath 

Well, that's it for this post. 

I hope you will find the script useful and if you have any suggestions or spot something that can be improved (I am no PowerShell Guru) leave me a comment to let me know. 

Until next time !! 

Monday, December 23, 2013

FIX: IE10 RSOP Warning Internet Explorer Branding. The specified procedure could not be found.

Whilst working on a new IE10 GPO, I have noticed that in RSOP a warning appears when the GPO tries to process the Internet Explorer Branding on Windows 7 clients with IE10 installed.


This is due to the fact that we cleaned out existing GPOs from Internet Explorer Maintenance settings by resetting them. As explained in this blog: http://deployhappiness.com/tracking-down-rouge-cses-ie-maintenance-addition/  this method of cleaning the IEM setting is necessary, if you consider the following scenarios:

"When you remove a setting in Group Policy, these settings are not instantly grabbed by clients. Because of this, GPOs will keep blank settings if you unconfigure certain CSEs. For example, you removed a setting for folder redirection. Three months goes by and a user returns from maternity leave. She logs into her computer and Group Policy sees the blank settings and makes adjustments. If the blank settings were not there, she would continue to apply the obsolete settings while everyone else has the current configs."

On the other hand having a warning on all your Windows 7 clients until Windows 7 End Of Life is just not right either.

The reason the warning keeps appearing is due to the fact that the Windows 7 GPO CSE is still trying to process Internet Explorer Branding extension whilst IE10 has replaced the IE GPO template on the client under:   "C:\Windows\PolicyDefinitions\inetres.admx"

This problem also shows on the client when enabling logging, as per this blog post.
In the GPSVC log you can read "Couldn't read extension Internet Explorer Branding's status"

So you now have two choices and depending whether you are using the same GPO to target IE8 and IE10 users you might opt for one option or the other. 

The first one is to  fully remove IEM references in the GPO. Options to do this are detailed in this MS article: http://support.microsoft.com/kb/2722241/en-us
If you have a GPO that is only applying to IE10 clients that would be the best option.

Now if you apply the same GPO to machines that could have either IE8 or IE10, I personally would rather keep the empty IEM reference in the GPOs to ensure all IE8 clients do get the instructions to remove IEM settings from their local cache and instead "patch" the windows 7 machines by removing from the registry the Internet Explorer Branding extension keys when installing IE10 on each client. 

To do this you need to take ownsership of the below registry keys and then delete them. The process is documented in this other MS article: http://support.microsoft.com/kb/2813272
You can then install IE10 and receive you IE10 GPOs without any warning under RSOP or in GPresult html reports.

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions\{A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B}

HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows NT\CurrentVersion\Winlogon\GPExtensions\{A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B}


I hope you find the info provided useful and do share your views and comments !! 

Until  next time, I wish you all a great time with friends and family to celebrate Christmas and new year and all the best for 2014 !



Friday, December 20, 2013

GOOD TO KNOW: GPO Override of UAC settings requires two reboots

Recently we got an issue with an application installer that would constantly throw an error when trying to register Oleaut32.dll.

Our packaging team found a work-around by Enabling the Group Policy setting for "User Account Control: Detect application installations and prompt for elevation".

Since this setting is disabled by default in our corporate environment to allow automated distribution of applications, we created a new GPO and set its precedence to apply after our baseline GPO and override our default corporate setting. This way machines can be set to temporarily receive this GPO to install this application.

Yet, when testing the solution we got mixed result.

After looking into those issues, we noticed that the override of this UAC settings required two reboots to be effective.

Our testing confirmed that when the machine first receives the new GPO - by running a GPUpdate /force and then rebooting - although RSOP and the registry were showing the correct settings the application was still throwing the same error at install time.
It was only after rebooting for a second time that the setting was fully applied and the installation worked.

The same was true when removing the machine from the filtering group to re-apply the standard settings.

Although we did know that Computer's GPO settings apply after a reboot having to reboot twice was rather unexpected.... Hope you find this info useful !

Wednesday, December 11, 2013

HOWTO Enable 8dot3 names when deploying Windows 7 with WinPE 4

8dot3 names are becoming less and less useful and is no longer enabled by default by Microsoft.

Here is one of the reason given in this article:
"The creation of 8.3 filenames and directories for all long filenames and directories on NTFS partitions may decrease directory enumeration performance. An 8.3-compliant file name refers to MS-DOS file-naming conventions. These conventions restrict file names to eight characters and restrict optional extensions to three characters."

A while ago we had an issue that 8dot3 names were no longer there. It turned out that the cause of the issue was that we had  mounted, edited and committed our WIM on a 2008R2 server where 8dot3 naming was disabled by default.
This caused some issues with some scripts relying on 8dot3 naming being present.

To check if 8dot3 names are present or not on a machine simply run
DIR /X C:\


It is important to check the root of the system drive because since the program files folder is always copied from the WIM to the disk this indicate whether the 8dot3 names are included in the WIM or not. Depending on how the following registry value is set you could have 8dot3 names created for new folder but missing for existing folders. All the details can be found in this TechNet article.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation

Now, starting with WinPE 4.0 even if you have captured a WIM with 8dot3 names enabled, after you apply your image with an MDT or SCCM task sequence that uses WinPE 4, in other words relying on ADK 8, 8dot3 names are disabled again when the disk is formatted.

To work around this problem you can add a Run Command step in your task sequence with the command:
cmd /c format %OSDISK% /fs:ntfs /q /v:SYSTEM /s:enable /y


Here is a link to the technet forum post were this solution is detailed. All credits goes to them.


Tuesday, December 10, 2013

PowerShell one liner to format VARIABLE.DAT content

When investigating deployment issues with MDT all the variables used during deployment are listed under MININT\SMSOSD\OSDLOGS\Variable.dat

The file itself is not really easy to read and as it comes all in 1 line not easy to compare either.

Here is a one line power shell command that creates a text file out of an exported Variable.DAT

[xml]$xml = get-content "C:\temp\VARIABLES.DAT"; $xml.MediaVarList.Var | format-table -wrap | Out-File C:\temp\Variable.dat.txt

Here is a screenshot with the output of the result at the top and the unformatted file at the bottom.