Some special characters in deployment type name cause applications not to Install

I recently stumble upon a bug in ConfigMgr that can cause issues with application deployments so that applications won’t install. When you are creating and application and gets to the step where you are supposed to create a Deployment type and you give the deployment type a name containing some certain special characters this will cause you not to be able to install the application when deployed to a collection.

 

Following special characters have been tested and won’t cause any issues:

/ & ! # @ –

 

These special characters will cause issues:

\ ”

Example

 

Here you have an example where the Name field contains a backslash “Install\Uninstall”.

 

 

 

When trying to Install the application that contains the backslash character it can look like this where it just keeps saying “installing..” and won’t continue until you go to another pane and back and you will see the “Install” button again

 

 

Here’s a another example with different app but with the same scenario for the deployment type name and it can show up is with an error message like this:

 

 

 

 

And in some instances the application won’t show up at all (app that should appear is WinRar 5.4.0)

 

 

Here’s a short video showing off the issue

 

 

Workaround

 

So whats the workaround if this happens? Well it’s pretty simple actually.

Just rename the deployment type and remove the special character that caused the issue and let the client run an application deployment evaluation cycle and the installation will continue just fine.

 

Se which special characters that i found so far that will work and won’t work in the beginning of this post.

 

Bug report has been filed to Microsoft

https://connect.microsoft.com/ConfigurationManagervnext/feedback/details/3138523

 

 

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

You can also find me over at

http://blog.coretech.dk/author/tan/

 

 

#application-install-issue, #bug-report, #configmgr, #configmgr-bug, #deployment-type

HP Elitebook 820 G4 – Bitlocker issue with BIOS firmware version 01.05

TLDR;

Bitlocker issue for model HP Elitebook 820 G4 with BIOS firmware 01.05. Solution: upgrade to 01.06

 

The following versions of the Elitebook also are affected and can use the same BIOS.

Elitebook 840 G4

Elitebook 850 G4

The issue

 

Earlier today I stumble upon an issue with the HP model Elitebook 820 G4 and bitlocker where during the startup it asked for BitLocker recovery key for no apparent reason.

In this specific scenario the Elitebook 820 G4 was replacing the old model Elitebook 820 G3 and just one week prior the Elitebook 820 G4 was implemented and installed without any issues. (What I didn’t know at the moment was that back then it was running BIOS version 01.03 and now it was running 01.05)

 

 

You could either input the bitlocker key and continue or just press ESC 3 times until you got in to BIOS and just press continue and the machine would continue without having to input any recovery key.

 

During the troubleshooting I made sure that the following things were as they should

 

  • Disk formated as GPT and not MBR – Checked
  • TPM 2.0 was enabled – checked
  • Legacy support disabled and Secure boot enabled – checked

and so on, there was nothing wrong with the configuration.

 

Still there was issues that not all the time but the majority of restarts the computer kept on asking for the bitlocker recovery key.

 

The solution

 

What I’ve found out was that the Firmware version 01.05 caused the issue. If you are running 01.03 you shouldn’t have this issue and on HP support site they just released a new version 01.06 so I updated and the problem was solved, no more bitlocker recovery key question during startup.

 

Checking the release notes for 01.06 from HP it also states it fixed issues with bitlocker:

 

 

Download link https://support.hp.com/us-en/drivers/selfservice/hp-elitebook-820-g4-notebook-pc/11122281

 

 

Thats all for now and Until next time, cheers !

You can also find me over at

http://blog.coretech.dk/author/tan/

 

 

 

 

#bitlocker, #bitlocker-recovery-key, #bitloker-issue, #hp-820-g4, #hp-elitebook-820-g4, #hp-elitebook-840-g4, #hp-elitebook-850-g4

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