Intune – Deploy required user settings to Windows 10 with powershell

In this blog I would like to describe, how I managed to set required user settings to Windows 10.
Since I still do have an On-Premises environment, in which also File Servers reside and a DFS Namespace is still up and running, I wanted to make sure to get the advantages of using the local network.
So here are my two use-cases to solve:
1. Add a Network location for the DFS Path if the user is logged on On-Premises
2. Modify the local “host” file, to redirect the workfolder clients to the file server internally

With this goals to achieve given, it was quite clear: It’s scripting time again *happy*
So I decided to create a single script, which I can use for both tasks. This means I need to check, if a user is running the script, or if it’s in System context. Due to the fact that the DFS link resides within the user profile, the script needs to run in user context. On the other hand the host file requires Admin permission for modifications. This is great, because within Intune, we can easily select, if the script should run in user or system context:

My solution to check if the script is running in system or in user context is the following line (I will provide the whole script at the end):

And the second important question is: Am I on the local network? For this, I simply check if I can reach port 389 of a known Domain Controller in my network:

With that is set, I was able to go ahead and define the settings that should get applied.
The first setting was creating a Network Location within Windows explorer if the domain controller is reachable, and if the DC is not reachable to remove the Link. For the creation of the Network location, I found a very nice function of Tom White on the TechNet Gallery:
Add-NetworkLocation – A function to create an advanced network location

Im simply took this function and implemented it in my script.
The following section creates the link if a DC is available, or it deletes the link:

This will cover the user settings. Now it’s up to the Host file. For modifying the host file, I have to make sure that the script is running in System Context, as it requires Administrative permission.
For adding or removing lines to the host file, I’m using those two functions (be aware, the search string is hard-coded):

So I then need only to trigger the correct function:

All is done for the script (again, for better readability of the blog, I post the whole script at the end), and I can go ahead, and test the solution through Intune. Just create a PowerShell configuration twice with the same script, where you configure one script running in user context, and the other in system context. I created a Azure AD security group and added my test machine to the group, this group I then used for both PowerShell Configuration Profiles.

And everything worked great:

So the first step of creating a script which does the job is done. Next up would be to deploy the script to the clients, because the Intune configuration would only run the script once. I’m thinking about to create a Script, which creates two scheduled tasks, one for the user and one for the system. The scheduled tasks would then be configured to run at user logon. But I am not sure about this yet, but I’m quite sure that I will create a blog about the final solution.

And here is the whole script:
Function Check-DCAvailable {
param(
[Parameter(Position=0,mandatory=$true)][string]$DCToCheck
)
#Check if DC is available on LDAP
$LDAPTestResult = $null
$LDAPTestResult = Test-NetConnection -ComputerName $LocalDomainController -Port 389 -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
if($LDAPTestResult.TcpTestSucceeded -ne $true) {
Write-Host ("Domaincontroller was not answering: " + $LocalDomainController) -ForegroundColor Yellow
return $false
}
else {
return $true
}
}

function Remove-HostFileWorkFolderEntry {
$hostFile = ($env:SystemRoot + "\System32\drivers\etc\hosts")
$hostFileContent = Get-Content -Path $hostFile
$hostFileContent = $hostFileContent | foreach{if(($_ -like "*workfolders.hosebei.ch*") -eq $true) { Write-Host $_ } else {$_}}
$hostFileContent | Out-File $hostFile -enc ascii

}

function Add-HostFileWorkFolderEntry {
$hostFile = ($env:SystemRoot + "\System32\drivers\etc\hosts")
$hostFileContent = Get-Content -Path $hostFile
if(($hostFileContent -contains "workfolders.hosebei.ch") -ne $true) {
$hostFileContent = $hostFileContent + "192.168.1.166 workfolders.hosebei.ch"

}
$hostFileContent | Out-File $hostFile -enc ascii

}

function Add-NetworkLocation

{
[CmdLetBinding()]
param
(
[Parameter(Mandatory=$true)][string]$networkLocationPath,
[Parameter(Mandatory=$true)][string]$networkLocationName ,
[Parameter(Mandatory=$true)][string]$networkLocationTarget
)
Begin
{
Write-Verbose -Message "Network location path: `"$networkLocationPath`"."
Write-Verbose -Message "Network location name: `"$networkLocationName`"."
Write-Verbose -Message "Network location target: `"$networkLocationTarget`"."
Set-Variable -Name desktopIniContent -Option ReadOnly -value ([string]"[.ShellClassInfo]`r`nCLSID2={0AFACED1-E828-11D1-9187-B532F1E9575D}`r`nFlags=2")
}
Process
{
Write-Verbose -Message "Checking that `"$networkLocationPath`" is a valid directory..."
if(Test-Path -Path $networkLocationPath -PathType Container)
{
try
{
Write-Verbose -Message "Creating `"$networkLocationPath\$networkLocationName`"."
[void]$(New-Item -Path "$networkLocationPath\$networkLocationName" -ItemType Directory -ErrorAction Stop)
Write-Verbose -Message "Setting system attribute on `"$networkLocationPath\$networkLocationName`"."
Set-ItemProperty -Path "$networkLocationPath\$networkLocationName" -Name Attributes -Value ([System.IO.FileAttributes]::System) -ErrorAction Stop
}
catch [Exception]
{
Write-Error -Message "Cannot create or set attributes on `"$networkLocationPath\$networkLocationName`". Check your access and/or permissions."
return $false
}
}
else
{
Write-Error -Message "`"$networkLocationPath`" is not a valid directory path."
return $false
}
try
{
Write-Verbose -Message "Creating `"$networkLocationPath\$networkLocationName\desktop.ini`"."
[object]$desktopIni = New-Item -Path "$networkLocationPath\$networkLocationName\desktop.ini" -ItemType File
Write-Verbose -Message "Writing to `"$($desktopIni.FullName)`"."
Add-Content -Path $desktopIni.FullName -Value $desktopIniContent
}
catch [Exception]
{
Write-Error -Message "Error while creating or writing to `"$networkLocationPath\$networkLocationName\desktop.ini`". Check your access and/or permissions."
return $false
}
try
{
$WshShell = New-Object -ComObject WScript.Shell
Write-Verbose -Message "Creating shortcut to `"$networkLocationTarget`" at `"$networkLocationPath\$networkLocationName\target.lnk`"."
$Shortcut = $WshShell.CreateShortcut("$networkLocationPath\$networkLocationName\target.lnk")
$Shortcut.TargetPath = $networkLocationTarget
$Shortcut.Description = "Created $(Get-Date -Format s) by $($MyInvocation.MyCommand)."
$Shortcut.Save()
}
catch [Exception]
{
Write-Error -Message "Error while creating shortcut @ `"$networkLocationPath\$networkLocationName\target.lnk`". Check your access and permissions."
return $false
}
return $true
}
}

#-----------------------------
#Main Script
#Variables
$LocalDomainController = "hosebeidc02.deheim.hosebei.ch"

#Determine if Script was started with system
$bSystemContext = ([Security.Principal.WindowsIdentity]::GetCurrent()).IsSystem

if($bSystemContext -eq $false) {
#Execute User Section

#Create Network Links
if(Check-DCAvailable($LocalDomainController)) {
#DC was found, we can assume getting a kerberos ticket for accesing SMB shares
Write-Host ("Connecting network locations") -ForegroundColor Green

#test if Hosebei DFSlink is existent, if not, create it
Write-Host ("Connecting Hosebei DFS") -ForegroundColor Green
if((Test-Path -Path "$env:APPDATA\Microsoft\Windows\Network Shortcuts\Hosebei DFS") -ne $true) {
$null = Add-NetworkLocation -networkLocationPath "$env:APPDATA\Microsoft\Windows\Network Shortcuts" -networkLocationName "Hosebei DFS" -networkLocationTarget "\\deheim.hosebei.ch\hosebeiDFSroot"
}
}
else {
#Remove existing Links
Write-Host ("Removing network locations") -ForegroundColor Yellow

#test if Hosebei DFSlink is existent, if true, remove it
Write-Host ("Remove Hosebei DFS Link due to no DC Access") -ForegroundColor Yellow
if((Test-Path -Path "$env:APPDATA\Microsoft\Windows\Network Shortcuts\Hosebei DFS") -eq $true) {
Remove-Item -Path "$env:APPDATA\Microsoft\Windows\Network Shortcuts\Hosebei DFS" -Force -Recurse
}
}
}
else {
#execute system Section

#Modify host file for Workfolder access
#Get HostFile
$hostFile = ($env:SystemRoot + "\System32\drivers\etc\hosts")
$hostFileContent = Get-Content -Path $hostFile
if(Check-DCAvailable($LocalDomainController)) {
#DC was found, we can directly access the file server
Add-HostFileWorkFolderEntry
}
else {
#No DC was found, we need to sync workfolders through the azure ad app proxy
Remove-HostFileWorkFolderEntry
}
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.