Baseline Evaluation with Run script feature in ConfigMgr 1706

 

One of the new pre-realease features in ConfigMgr 1706 is the Run Script function which makes it possible to run Powershell scripts directly from the ConfigMgr console towards clients. This is a huge benefit to be able to do so because this means as long as the client is active in ConfigMgr console it will execute the script you triggered almost in real time and without going through the process of making sure that WinRM is active on the client and configuring firewall and all the other things that can be an issue when you deal with clients on different subnets, physical locations, behind different firewalls etc. As long as you have your ConfigMgr infrastructure in place and the clients are active you are all good to go.

 

What you could do and as I will showcase in this post is to invoke Configuration baseline evaluation on demand with the Run script function. I have an old blog post on how to to it with Powershell remotely ( https://timmyit.com/2016/07/26/sccm-and-powershell-trigger-baseline-evaluation-on-client/ ) but that means you have to have everything in place to remote access clients with Powershell which isn’t always the case in a lot of environments for many reasons.

The reason for creating this script in the first place is because there’s no built in function to evaluate baselines on demand in ConfigMgr. I have also created an uservoice to add that function in the UI console here: https://configurationmanager.uservoice.com/forums/300492-ideas/suggestions/18652852-console-ui-function-to-invoke-evaluation-of-baseli

Give that uservoice a vote if you find it useful and in the mean time we can use the run script function to achieve the same result.

 

If you want to know in detail how to active the run script feature in ConfigMgr 1706 and how to create a script and run it in detail check out my blog posts about that over at CTGlobalservices blog:

 

http://blog.ctglobalservices.com/powershell/tan/how-to-activate-the-new-feature-run-powershell-scripts-from-the-configmgr-console-on-current-branch-1706/

http://blog.ctglobalservices.com/powershell/tan/create-and-run-scripts-with-the-new-feature-run-powershell-scripts-from-the-configmgr-console-on-current-branch-1706/

 

Baseline Evaluation with Run script feature

 

Here’s the Powershell script we want to use to evaluate all of the baselines deployed to the machines in a device collection. If you just want to evaluate a specific one you need to modify the script.

 

Note,

When testing this script as a Run script I wasn’t able to run the original Powershell script as a function, it returned Exit code 0 but didn’t execute the evaluation method on the client for some reason through ConfigMgr but it did work when I ran it manually on the client. I’m currently troubleshooting that and will probably file a bug report when I have more info and do a separate blog post on that later. But in the meantime we will just have to skip function part. And just to emphasis this is still a prerelease feature.

 


$Baselines = Get-WmiObject -ComputerName $env:COMPUTERNAME -Namespace root\ccm\dcm -Class SMS_DesiredConfiguration
$Baselines | % {

([wmiclass]"\\$env:COMPUTERNAME\root\ccm\dcm:SMS_DesiredConfiguration").TriggerEvaluation($_.Name, $_.Version)

}

 

First off all, lets create a script

 

Copy the or import the powershell script

 

Approve the script you just created.

 

 

Over at the client you can see that we have a Baseline that hasn’t been evaluated yet

 

Jumping back to the ConfigMgr console we find the device collection we want to run the script against and then right click and choose “Run Script” and go through the wizard

 

 

Under Client operations we can see that the operation has started

 

And under monitoring and “Script Status” we see that the evaluation has completed on the client.

 

 

and finally over at the client we see that the Baseline has been evaluated.

 

That’s all for now and until next time, cheers !

Don’t forget to follow me on twitter

 

And you can also find me blogging over at http://blog.ctglobalservices.com/

Import boundaries to SCCM with powershell

 
This is the second blog post in a series of two where the first one was about exporting boundaries from ConfigMgr to .CSV files and you can check out that post here: https://timmyit.com/2017/04/25/export-boundaries-from-sccm-with-powershell/

Now its time for us to import it to ConfigMgr and it’s very simple to do, all you need is the powershell script listed below (it’s also available over at technet for download https://gallery.technet.microsoft.com/Import-boundaries-from-46b9a894 )

 

What do we want to achieve?

We want to be able to import the boundaries we exported in to .CSV files from the https://timmyit.com/2017/04/25/export-boundaries-from-sccm-with-powershell/ guide and have them to show up in ConfigMgr. There’s no built in feature to export and import boundaries as of now in ConfigMgr so that’s why we turn to powershell to help us out with this process.

 

 

The Script

 

<#   
    .NOTES
    ===========================================================================
     Created on:    4/10/2017 
     Modified on:   4/21/2017 
     Created by:    Timmy Andersson
     Twitter:       @TimmyITdotcom
     Blog:          www.timmyit.com
    ===========================================================================
    .DESCRIPTION
        Import Subnet an IPRange Boundries to CSV files. This script needs to run on the siteserver to work. 
        Specify source path with the parameter -SourcePath
#>
[CmdletBinding(DefaultParameterSetName = 'SourcePath')]
param
(
[Parameter(Mandatory = $true,
Position = 1)]
$SourcePath
)

Begin{
$SiteCodeObjs = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $env:COMPUTERNAME -ErrorAction Stop
	foreach ($SiteCodeObj in $SiteCodeObjs)
	{
		if ($SiteCodeObj.ProviderForLocalSite -eq $true)
			{
			$SiteCode = $SiteCodeObj.SiteCode
			}
	}
$SitePath = $SiteCode + ":"
Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0, $Env:SMS_ADMIN_UI_PATH.Length - 5) + '\ConfigurationManager.psd1')
}
Process
{
	$Subnets = (Import-csv "$SourcePath\BoundariesIPSubnet.csv") 
	$IPRanges = (Import-csv "$SourcePath\BoundariesIPRange.csv" )


Set-Location $SitePath
			If ($Subnets -ne $null)
			{
				Foreach ($Subnet in $Subnets)
					{
					 New-CMBoundary -Type IPSubnet -Value "$($Subnet.Value)" -Name "$($Subnet.Key)"
					}
			}

		If ($IPRanges -ne $null)
			{
				Foreach ($IPRange in $IPRanges)
					{
					 New-CMBoundary -Type IPRange -Value "$($IPRange.Value)" -Name "$($IPRange.Key)"
					}
			}
}


 

 

Example

  •  Save the script and run it from your site server
  • Call the script and specify the parameter -SourcePath for where you saved the .csv files that was created with the Export-Boundaries.ps1 script
    • Import-Boundaries.ps1 -SourcePath C:\temp\boundaries
  • Once the script finished the boundaries should be imported to your ConfigMgr environment.

 

 

Remember that you still need to create boundary groups and link them to your boundaries once your done with the import.

 

Until next time, cheers !

You can find me over at

Export boundaries from SCCM with powershell

This blog post is the first in a series of 2 where i will showcase how to export iprange and subnet boundaries and then how to import them with the help of a powershell script. I’m a big proponent for automating task to increase productivity and I believe in the mindset of always trying to improve what ever you are doing, regardless if that’s improving your workflow or learning something new to improve yourself. Invest time now to save time later but lets get back to the topic of this post and that’s about exporting boundaries from SCCM.

 

Part 2, Importing boundaries can be found here: https://timmyit.com/2017/05/02/import-boundaries-to-sccm-with-powershell/

What do we want to achieve?

For example If you are in the process of setting up a new ConfigMgr environment and there’s an existing ConfigMgr environment that’s getting decommissioned but you aren’t performing a site migration and there’s still information like boundaries that
will be reused then here’s a script that will help you export IPRange and Subnet boundaries to .csv so you later can import them in the new environment because there’s no built in function in ConfigMgr to do that at the moment.

In the picture below we have our boundaries we want to export in to a file (in this case a .csv) and then later be able to import them back in to ConfigMgr.

 

 

 

The script


<#   
    .NOTES
    ===========================================================================
     Created on:    4/10/2017 
     Modified on:   4/21/2017 
     Created by:    Timmy Andersson
     Twitter:       @TimmyITdotcom
     Blog:          www.timmyit.com
    ===========================================================================
    .DESCRIPTION
        Export Subnet an IPRange Boundaries to CSV files. This script needs to run on the siteserver to work. 
		Specify Destination path with the parameter $DestinationPath
#>
[CmdletBinding(DefaultParameterSetName = 'DestinationPath')]
param
(
[Parameter(Mandatory = $true,
Position = 1)]
$DestinationPath
)
BEGIN
{
 
$SiteCodeObjs = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $env:COMPUTERNAME -ErrorAction Stop
	foreach ($SiteCodeObj in $SiteCodeObjs)
	{
		if ($SiteCodeObj.ProviderForLocalSite -eq $true)
		{
		$SiteCode = $SiteCodeObj.SiteCode
		}
	}

$SitePath = $SiteCode + ":"
 
Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0, $Env:SMS_ADMIN_UI_PATH.Length - 5) + '\ConfigurationManager.psd1')
 
}
PROCESS
{
	 
    Set-Location $SitePath
	$BoundriesSubnet = (Get-CMBoundary -BoundaryName * | Where-Object {$_.BoundaryType -like "0"})
	$BoundriesRange = (Get-CMBoundary -BoundaryName * | Where-Object {$_.BoundaryType -like "3"})
    $ErrorActionPreference = 'Continue'
    $IPrange = $null
    $IPrange = @{}
    $IPSubnet = $null
    $IPSubnet = @{}

	If ($BoundriesSubnet.count -gt "0")
	{
		foreach ($Boundry in $BoundriesSubnet)
			{
				$IPrange.Add($($Boundry.DisplayName),$($Boundry.Value))

			}
				$IPrange.GetEnumerator() | export-csv "$DestinationPath\BoundariesIPSubnet.csv" -NoTypeInformation -Encoding Unicode
	}
	If ($BoundriesRange.count -gt "0")
	{
		foreach ($Boundry in $BoundriesRange)
			{
				$IPSubnet.Add($($Boundry.DisplayName),$($Boundry.Value))

			}
				$IPSubnet.GetEnumerator() | export-csv "$DestinationPath\BoundariesIPRange.csv" -NoTypeInformation -Encoding Unicode
	}
		
}
END
{
	Invoke-Item $DestinationPath
}




Example

 

  •  Save the script and run it from your site server
  • Call the script and specify the parameter -DestinationPath for where you want to output the .csv files that gets created to.
    • Export-Boundaries.ps1 -DestinationPath C:\temp\boundaries
  • Once the script finished the destinationPath you specified will open up in explorer and you will find 1 files for iprange boundaries and one for subnet depending on what you have in your environment.

 

There you have it, its pretty simple and saves a lot of time if there’s a lot of boundaries to manually create in the new environment.

Next blog post will be about how to import the exported boundaries to ConfigMgr with the help of powershell.

Part 2, Importing boundaries can be found here: https://timmyit.com/2017/05/02/import-boundaries-to-sccm-with-powershell/

 

Until next time, cheers !

You can find me over at

Powershell script to retrieve all detection method scripts and output them


Last year i wrote a blogpost about how to get all the powershell scripts used as detection methods and since then i have refined that script a bit and also added logic for it to now output any detection method using scripts regardless if its Powershell, VBScript or Javascript.

I hope this can be useful to someone out there in cyberspace.

 

The Script

 


<#	
	.NOTES
	===========================================================================
	 Created on:   	12/06/2016 
	 Modified on:   3/31/2017 
	 Created by:   	Timmy Andersson
	 Contact: 		@Timmyitdotcom
	===========================================================================
	.DESCRIPTION
		Retreives and outputs scripts used by detection methods. 
#>
[CmdletBinding(DefaultParameterSetName = 'DestinationPath')]
param
(
[Parameter(Mandatory = $true,
Position = 1)]
$DestinationPath
)

BEGIN
{
[String]$Filepath = $DestinationPath

$SiteCodeObjs = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $env:COMPUTERNAME -ErrorAction Stop
foreach ($SiteCodeObj in $SiteCodeObjs)
{
if ($SiteCodeObj.ProviderForLocalSite -eq $true)
{
$SiteCode = $SiteCodeObj.SiteCode
}
}
$SitePath = $SiteCode + ":"

Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0, $Env:SMS_ADMIN_UI_PATH.Length - 5) + '\ConfigurationManager.psd1')

}
PROCESS
{
if (-not (Test-Path $DestinationPath))
{
new-item -Path $DestinationPath -ItemType Directory -Force
}

Set-location $SitePath

$Apps = (Get-CMApplication)
foreach ($App in $Apps)
{

$Script = ([Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::DeserializeFromString($App.SDMPackageXML)).DeploymentTypes[0].Installer
if ($Script.DetectionScript -ne $Null)
{
$PSscript = ([Microsoft.ConfigurationManagement.ApplicationManagement.Serialization.SccmSerializer]::DeserializeFromString($App.SDMPackageXML)).DeploymentTypes[0].Installer.DetectionScript

Switch ($PSscript.Language)
{
"PowerShell" { Out-File -FilePath "$Filepath$($App.LocalizedDisplayName).ps1" -InputObject $PSscript.Text }
"VBScript" { Out-File -FilePath "$Filepath$($App.LocalizedDisplayName).vbs" -InputObject $PSscript.Text }
"JavaScript" { Out-File -FilePath "$Filepath$($App.LocalizedDisplayName).JS" -InputObject $PSscript.Text }
}

}

}

}
END
{
}

Example

 

You need to run script locally from your siteserver.

get-DetectionMethodScripts.ps1 -DestinationPath "C:\temp\scripts\"

 

and it will output all the detection methods that uses scripts to that folder. One for each application and names the file after the application.

 

Until next time, cheers !

You can find me over at

Powershell script to output every direct rule WMI query used by device collections in ConfigMgr

I want to share a script that came about after i wanted to get hold of all the WMI-queries that’s been created and used for populating different device collections without need to go in to every single one of them and extract the query manually. Especially if you are dealing with larger environments who might have hundreds of device collections and first of all figuring out which one actually uses WMI-queries and who doesn’t.

 

What do we want to achieve

Extracts all the WMI-queries used in SCCM and outputs them in to a .txt files for each Device Collection.

 

The Script

 

<#	
	.NOTES
	===========================================================================
	 Created on:   	3/30/2017 
	 Created by:   	Timmy Andersson
	 Contact: 	@Timmyitdotcom
	===========================================================================
	.DESCRIPTION
		Extracts all the WMI-queries used in SCCM and outputs them in to a .txt files for each Device Collection. 
#>
[CmdletBinding(DefaultParameterSetName = 'DestinationPath')]
param
(
	[Parameter(Mandatory = $true,
			   Position = 1)]
	$DestinationPath
)

BEGIN
{
	[String]$Filepath = $DestinationPath
	
	$SiteCodeObjs = Get-WmiObject -Namespace "root\SMS" -Class SMS_ProviderLocation -ComputerName $env:COMPUTERNAME -ErrorAction Stop
	foreach ($SiteCodeObj in $SiteCodeObjs)
	{
		if ($SiteCodeObj.ProviderForLocalSite -eq $true)
		{
			$SiteCode = $SiteCodeObj.SiteCode
		}
	}
	$SitePath = $SiteCode + ":"
	
	Import-module ($Env:SMS_ADMIN_UI_PATH.Substring(0, $Env:SMS_ADMIN_UI_PATH.Length - 5) + '\ConfigurationManager.psd1')
	
}
PROCESS
{
	if (-not (Test-Path $DestinationPath))
	{
		new-item -Path $DestinationPath -ItemType Directory -Force
	}
	
	Set-location $SitePath
	
	$AllDC = (Get-CMDeviceCollection).Name
	Foreach ($Devicecollection in $AllDc)
	{
		$CollectionMR = Get-CMDeviceCollectionQueryMembershipRule -CollectionName "$Devicecollection"
		if ($CollectionMR -ne $null)
		{
			$Query = $CollectionMR.QueryExpression
			Out-File -FilePath "$DestinationPath$($Devicecollection).txt" -InputObject $Query
		}
		
	}
}
END
{
}




Example

 

Run this script from your Site server, only variable you need to pass through to the script is the destination path you want the source files to be output to

Note: If the folder doesn’t exist the script will create it for you

 

Get-DeviceCollectionsQueries.ps1 -DestinationPath "C:\Temp\Queries\"

When the script is finished go to your destination folder and you will find the all the different device collections and their WMI queries.


 

Until next time, cheers !

You can find me over at

#configmgr, #device-collections, #powershell, #sccm, #wmi

LAPS Powershell installation script for Domain controllers

Continuing with LAPS, if you don’t know what LAPS is you should read this

https://technet.microsoft.com/en-us/mt227395.aspx?f=255&MSPPError=-2147217396

And take a look at my earlier post

https://timmyit.com/2017/03/19/quick-overview-of-local-administrator-password-solution-laps/

 

Steps to Install

So, I created a powershell script that will help install LAPS on your DC and configure most of the things automatically tho there’s still a few steps that needs to be done manually which i will go through below. with that said i highly recommend you go through the documentation from Microsoft so you have a good understanding on what LAPS is and how to Install it manually and all the prerequisites before you use this script because this script doesn’t cover every installation scenario that’s possible and you need to be able to understand when this script is suitable and when its not and make the desired changes needed to make it work for your specific scenario.

 

1. Download the LAPS installation files from Microsoft https://www.microsoft.com/en-us/download/details.aspx?id=46899

2. Copy the files to your Domain Controller you wish to install it on

3. Put the Install-DC.ps1 in the same folder as the installation files

 

     4. Create a security group that will contain members who will be able to read/reset the LAPS Password (For example a group called PwdAdmins)

      5. Navigate to the OU in AD where all the computer objects are located that you will manage

6. Remove Extended rights on all the groups that shouldn’t be able to retrieve or change the LAPS Password (For me information see Section 2.2.1 Removing Extended Rights in LAPS_OperationsGuide.docx document from Microsoft)

 

6. Open Powershell as an Administrator and navigate to the source folder

7. Run the following command Install-DC.ps1 -ADCompOU <Your OU> -ADUserGroup <Your user security group> (Example. Install-DC.ps1 -ADCompOU Win10PCs -ADUserGroup PwdAdmins)

 

 

The Script

 

param (
 [Parameter(Mandatory = $true, HelpMessage = 'AD OU that contains the computers you want to manage LAPS with')]
 [string]$ADCompOU,
 [Parameter(Mandatory = $true, HelpMessage = 'AD Security group that contains users who should get access to read LAPS PW')]
 [string]$ADUserGroup
)
 
 
 
 $Props = ("ADDLOCAL=Management.UI", "ADDLOCAL=Management.PS", "ADDLOCAL=Management.ADMX")
 
 foreach ($Prop in $Props)
 {
 if ([System.Environment]::Is64BitProcess)
 { 
 msiexec /q /i LAPS.x64.msi $Prop ALLUSERS=2
 }
 Else
 {
 msiexec /q /i LAPS.x86.msi $Prop ALLUSERS=2
 }
 }
 
 Import-module AdmPwd.PS
 Update-AdmPwdADSchema

 
 Set-AdmPwdComputerSelfPermission -Identity $ADCompOU
 Set-AdmPwdReadPasswordPermission -Identity $ADCompOU -AllowedPrincipals $ADusergroup
 Set-AdmPwdResetPasswordPermission -Identity $ADCompOU -AllowedPrincipals $ADusergroup
 

 

Until next time, cheers !

You can find me over at

#domain-controllers, #install-laps, #laps, #powershell

Hardware inventory – Add firmware property to WMI class Win32_Diskdrive in ConfigMgr

 

There was a question on the Tech konnect facebook group the other day if there was any way of collecting disk name and firmware version from your clients in ConfigMgr.

Yes you can do this with the help of Hardware inventory and the Win32_DiskDrive WMI Class and use the following properties Caption and Firmware Revision but the thing is that the property Firmware Revision isn’t available by default so we need to add this
to the Win32_DiskDrive class in ConfigMgr Hardware inventory and i’m going to show you how to do this with the help of Powershell.

 

Getting started

First of all lets have a look on a Win10 client pc just to show of the information we want to gather. Caption is a good way of finding out the name and model of the disk tho different manufactures has there own way of naming things and then Firmware Revision to find out what firmware its running.

 

Get-WmiObject -Class Win32_DiskDrive | Format-List -Property Caption, Firmwarerevision

 

 

 

If we turn to ConfigMgr and Hardware Inventory classes Administration – Client Settings – <Your Client Setting> – Properties – Hardware Inventory – Set Classes

We can see that under the Win32_DiskDrive class we already have Caption but there’s no Firmware Revision property to be found.

 

 

 

Adding Firmware Revision to the Win32_DiskDrive class in ConfigMgr

 

We are going to this with the help of Powershell and here’s the script

Note: Make sure to modify the $Namespace variable so that the Site_Code is correct for your environment

 

  

#Modify Namespace to your correct Site ID
$Namespace = "root\SMS\site_TS1"

$Win32_DiskDrive = (Get-WmiObject -Namespace $Namespace -Class SMS_InventoryClass -ComputerName localhost | Where-Object {$_.ClassName -like "Win32_DiskDrive"})
$Classprop = [wmiclass]"$($Namespace):SMS_InventoryClassProperty"

$Prop = $Classprop.CreateInstance()
$Prop.PropertyName = 'FirmwareRevision'
$Prop.IsKey = $false
$Prop.Type = 8
$Win32_DiskDrive.Properties += [System.Management.ManagementObject]$Prop
$Win32_DiskDrive.Put()

 

Run the script on your ConfigMgr Siteserver

 

 

Go back to ConfigMgr and Administration – Client Settings – <Your Client Setting> – Properties – Hardware Inventory – Set Classes

and under Win32_DiskDrive you will now find “FirmwareRevision” and lets mark that checkbox and press “ok”

 

 


 Now you need to wait for the next Hardware inventory data to get back in to ConfigMgr and onces thats done you can go to “Assets and Compliance – Devices – <Right click on a Client> – Start – Resource Explorer”

 

 

 

 And from here go to “Hardware – Disk Drives” and double click on the row to the right which indicates the different disk and you will get a list of all properties and there you also have Firmware Revision

 

 

 

Now when you have the data in ConfigMgr  you can make a report out of it or build collections and so on.

Post any question below or hit me up on twitter.

 

 

Until next time, cheers !

You can find me over at

#modify