EICAR Standard Anti-Virus Test File

Recently a customer was testing antivirus scanning software, both on trafic and on servers/clients. This had to be tested on several environments, including production and really didnt want to use a real infected file. The following showed up, didn’t know about it, chances are there are others that doesnt know about this.

“The EICAR Standard Anti-Virus Test File or EICAR test file is a computer file that was developed by the European Institute for Computer Antivirus Research (EICAR) and Computer Antivirus Research Organization (CARO), to test the response of computer antivirus (AV) programs. Instead of using real malware, which could do real damage, this test file allows people to test anti-virus software without having to use a real computer virus.

Anti-virus programmers set the EICAR string as a verified virus, similar to other identified signatures. A compliant virus scanner, when detecting the file, will respond in exactly the same manner as if it found a harmful virus. Not all virus scanners are compliant, and may not detect the file even when they are correctly configured.

The use of the EICAR test string can be more versatile than straightforward detection: a file containing the EICAR test string can be compressed or archived, and then the antivirus software can be run to see whether it can detect the test string in the compressed file.”

EICAR test file – Wikipedia, the free encyclopedia

Steps to use it:
Create a .txt file on your drive, open your AV scanner software and create an exclusion on this file and location. Update the contents of the file with the referenced. Scanner software will not quarentine it with that name and location, however anywhere you move it, it should be detected and removed.

Recover Windows service account passwords

Ever encountered the situation where you don’t know the password of one or more services running on your windows server? – Well I have, lots of time. Lack of documentation, lost people, lost passwords, typos you name it, I’ve seen it. By chance, I stumpled upon a few articles describing a seamless easy way to retrieve all these passwords and of course asked my good friend Mads Hjort Larsen to concoct a user friendly version of this script and so he did!

Now while this is a nice way to pull out lost service account passwords. It will also serve as a grand reminder about DO NOT use Domain Administrator accounts as service accounts. DO NOT use personal accounts for services. The passwords are really THAT easy to retrieve.
Dont trust me? – try it for your self, I dare you πŸ™‚


Configure Azure Application Proxy application for CRM Internet Facing Deployment

The task was to configure an existing CRM IFD, with an existing ADFS / Azure Application Proxy infrastructure.

CRM IFD deployment was already working and implemented for internal access. What was missing was the external access through Azure Application Proxy.
Following this guide: https://azure.microsoft.com/en-us/documentation/articles/active-directory-application-proxy-publish/
With the following configuration will get you there:

Note that once you have the CRM Internet facing deployment done, no changes are required on CRM or ADFS. The below is only the Azure Application Proxy configuration required for CRM internet facing deployment.

Logon to manage.windowsazure.com and create a new Application under Active Directory.
Important configuration is:
– External URL: You can use the same URL as internally, however make sure that CNAME record is created as well as certificate is uploaded. This is referred to as custom domain.
– Preauthentication Method: Passthrough
– Translate URL in headers: No

You need to add required CRM IFD service url’s:
organisation, authentication and/or discovery service as seperate applications.


SharePoint Online – Performance – Basic Troubleshooting

Classic case: Customer reports in “SharePoint Online performance is slow. [period]”
Account Manager, Product Manager, Project Manager comes running 4 weeks after due date, customer wont accept the solution with the given performance. Ok…. Lets gather the tools for first steps:

Toolbox includes at this point
– PSping utility from PSTools(PSTools )
– Tracert utility from Microsoft (TraceRT )
– Browser Development Tools (F12 for Internet Explorer, Firefox or Chrome)

First step
Compare performance from your location with the client location using the Browser development tools. Are they the same?
If yes, problem usually lies in the configuration of SharePoint Online. Start testing from your location and don’t bother asking customer for client computer, remote login, network information.
If no, problem usually lies from customer client machine and SharePoint Online server. Start testing from customer client machine at their location. Ask them for information regarding their network configuration. Do they have proxy? Are they running old router/switch between?

When you have determined the location of your challenge, proceed to second step.

Second step
Second step of troubleshooting SharePoint Online performance is to measure ping time to the tenant as well as traceroute in order to locate route and geolocation of the tenant.
I use the following to complete that, either run it myself or ask the client to run it from their location.
psping.exe -n 20 tenant.sharepoint.com:443 > PsPingResult.txt
timeout 30 /nobreak
tracert tenant.sharepoint.com > TracertResult.txt
timeout 30 /nobreak

From that I derive the following:
1: For optimal performance, ping time is between 30-50ms stable.
2: Number of Route hops between 12-15.
3: Use https://www.iplocation.net/ to get most likely geolocation of tenant from returned public IP.

Psping.exe is part of SysInternals PSTools package.

Lastly again back to developer tools.
Collect performance report and look for errors in the console. Look for external http requests, certificate validation errors, script errors.

What the numbers show you
A: Ping times of more than 50MS or route hops more than 12-15 would lead me to look at the network with possible causes being:
Linespeed, old or outdated network equipment, tenant geolocation, proxy filtering, non-optimal routing.

B: Usually there are little or no problems in the direct network measurement and it will come down to the browser Development Tools. Note the difference between DOM loaded and Fully rendered. Client really dont care about DOM download, as they are only interested in the fully rendered page. So what can be causes of slow rendered pages:
Certificate errors, script errors, poor client hardware, proxy filtering, Antivirus, Poor coding.

Certificate Expiry – All Domain Servers – Powershell

This is a most lovely little piece of powershell.
“This script connects to the DC, gets a list of machines with the β€œOperatingSystem” value set to β€œ*Server*”, if it can succesfully ping the machine(s), it will return a list of certificates that expire after the date specified and compile a CSV file of the results.”

Do check it out and give probs to the man producing the most awesome powershell and now finally with his own blog πŸ™‚

Certificate Expiry

How to configure SharePoint trusted identity provider for UPN

#-- Add Certificates to SharePoint certificate store.
#-- Select Token signing Certificate
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2("D:\Certs\TokenSign\TokenSign.cer")

#-- Add Token signing Certificate to SharePoint trusted store
New-SPTrustedRootAuthority -Name "Token Sign ADFS 3.0" -Certificate $cert

#-- Creating Claim mapping
$emailClaimMap = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" -IncomingClaimTypeDisplayName "EmailAddress" -SameAsIncoming
$upnClaimMap = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" -IncomingClaimTypeDisplayName "UPN" -SameAsIncoming
$roleClaimMap = New-SPClaimTypeMapping -IncomingClaimType "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" -IncomingClaimTypeDisplayName "Role" -SameAsIncoming

#-- Creating Trusted Identity Provider for SharePoint
#-- Share IdP realm
$realm = "urn:sharepoint:extranet"

#-- URL for the IdP solution
$signInURL = "https://sts.contoso.com/adfs/ls/"

#-- Name of IdP 
$ProviderName = 'Extranet ADFS'

#-- IdP Token issuer for SharePoint
New-SPTrustedIdentityTokenIssuer -Name $ProviderName -Description 'Contoso Federated Authentication - External' -realm $realm -ImportTrustCertificate $cert -ClaimsMappings $emailClaimMap, $UPNClaimMap, $RoleClaimMap -SignInUrl $signInURL -IdentifierClaim $UPNClaimmap.InputClaimType

How to configure Outgoing email in SharePoint with O365 – SMTP relay

How to configure Outgoing email in SharePoint with O365, SMTP relay.
You might have moved all your mail accounts to O365, but you still have that on-premises SharePoint server, that needsΒ to send alerts or has some similar message functionality. Previously you had an Exchange server and used that as relay. Now you need to use O365, so how do you do that? Lets have a look at the prerequisites first and then I’llΒ show youΒ how to put it all together to send messages, both internally and externally if required.

– Service account in O365 with a mailbox; Used for authenticating SMTP request towards O365.
– Local SMTP server; Used for anonymous access toΒ SharePoint SMTP.
– DNS record; Used as SMTP relay address internally.
– External IP address of local SMTP server; Used for SPF record registration.
– SPF record of mail domain; Used to validate the local SMTP server against public mail exchangers.
– Certificate that covers SMTP relay DNS address; This is used to provide required TLS encryption.
– Internal IP of SharePoint server(s); Used to allow the relay through local SMTP server.

SPF record
First thing to do is update your SPF record for your domain. This is done on your mail domains DNS settings and should be a text file.

SPF v=spf1 ip4: include:spf.protection.outlook.com ~all

Install the matching certificate in the Personal store on the server.

If you do not have a local SMTP server already, you can install one using Roles and Features from within WindowsΒ Server.
To enable logging on the SMTP server, open IIS 6.0 Manager, expand your server and right click Properties. On the General tab; Check “Enable logging” and click Properties. Change log file directory to something different than your system drive.
On the Advanced Tab; Check the following Extended logging options:
Date (date),Β Time (time),Β Client IP Address (c-ip),Β Server Name (s-computername),Β Server IP Address (s-ip),Β Server Port (s-port),Β URI Query (cs-uri-query),Β Protocol Status (sc-status) andΒ Protocol Substatus (sc-substatus).

Note: Take into consideration where you place the respective SMTP server folders. It is strongly recommended that youΒ place them on a drive separate fromΒ the system drive.

IIS Configuration
Open IIS 6.0 Manager (which will be used to manage your SMTP server), expand your server and right click Properties on your SMTP Virtual Server.
On the access tab; under Secure communication it should state: “A TLS certificate is found with expiration date:Β “.
Click Authentication and verify that Anonymous access is enabled.
Click Relay, and select “Only the list below” and add the internal IP address of your SharePoint server(s). Leave the “Allow all computers which successfully authenticate to relay….”Β checked (this means that, all computers within the same domain may use this as a relay. IF you have infected machines, you want to disable this, or remove the infection).
Under the delivery tab; Click Outbound Security.
Check Basic authentication and type in your O365 service account information.
For example:

User name: svcRelayO365@contoso.com
Password: Ninja1234

Make sure TLS encryption is Checked and click Ok.
Click Outbound connections and change TCP port to 587 and click Ok.
Click Advanced, and type in the local DNS address of your internal relay and type in the SMART host smtp.office365.com and click Ok.


O365 Configuration
Login to portal.office365.com and navigate to Administration and Exchange.
In Office 365, click Admin, and then click Exchange to go to the Exchange Admin Center.
In the Exchange Admin Center, click Mail Flow, and click Connectors.
To add a new connector, click the + symbol and select From: “Your organization’s email server”, To: “Office 365” and click Next.
Choose the option “By verifying that the IP address of the sending server matches one of these IP addresses that belong to your organization”, and add the External IP address.
Leave all the other fields atΒ their default values, and select Save.

SharePoint Configuration
Open Central Administation and click System Settings.
Click Configure outgoing e-mail settings.
Use the DNS name of your internal SMTP server as Outbound SMTP server and the From address should match that of your service account.

Testing & Troubleshooting
On your local SMTP server, create a file, called email.txt with the following content:

SUBJECT: Test email
This is a test email sent from my SMTP server

Copy this file into the Pickup folder of your SMTP server. The server will process this and move it to the Queue folder and processΒ it for delivery to O365.
If you do not receive an email at your personal email address within 5 minutes, something is wrong. Here is how to check.
Go to your log file directory, configured previously and have a look at the error codes provided there.
If they are β€œqueued for delivery”, you move to the Office365 Portal and use the mailflow function and search for your mails. There they will be listed with a status indicating their state. The details of the Office365 mailflow log are comprehensive.

From SharePoint

$email = "test@test.com"
$subject = "Test subject"
$body = "Test body"
$site = New-Object Microsoft.SharePoint.SPSite "http://sharepoint"
$web = $site.OpenWeb()
// A True or False will confirm the message has been sent or not



Disable unsafe ciphers and SSL 2.0/3.0 on your server

One step to improve the security on your servers, would be to disable SSL 2.0 and 3.0 as well as the unsafe ciphers RC4. This can be done using the following registry changes on your server.
Note: When you disable SSL 2.0 and 3.0 on your servers, clients will no longer be able to connect using that. See this post for additional reference.

RC4 Cipher

Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128/128]
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 40/128]
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 56/128]

SSL 2.0 and 3.0

Windows Registry Editor Version 5.00
[HKey_Local_Machine\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0]
[HKey_Local_Machine\System\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0]


Windows 10 – Privacy settings – Automated

There has been quite some interest in the general privacy settings of the different applications and systems that we use in our daily life. Windows 10 is no exception to this, as Microsoft now by default, has chosen for you that you are very interested in sharing your traffic information with them. You can of course disable this tracking, however it is not always obvious how to do so. Once again my friend Mads Hjort Larsen has created a script to automate these privacy settings for you.

Have a look at the section “What should be changed” and make sure you change accordingly. ($false or $true)

Also note that once again WordPress has decided to mess with the formatting/syntax highlighting of the script. That is also why the third link in the comment section is surround by apostrophes.

    This script automates the changing of a lot of settings that are otherwise hard or tedious to change.
    This script consolidates a lot of Windows registry changes and changes to other operating system settings, 
    that affect the appearance and functionality of the Windows 10 operating system, with the intent of making
    it more userfriendly and increasing the privacy.
    Created by Mads Hjort Larsen
    email: mads.hjort.larsen@gmail.com

# What should be changed:
[bool]$privacySettings = $true  # change the settings related to privacy
[bool]$removeSoftware  = $false # remove Cortana, OneDrive and Metro Apps
[bool]$windowsUpdates  = $false # setup updates to NOT automatically reboot or download via P2P
[bool]$UIsettings      = $false # make win 10 look more like win 7/8/8.1

########### DO NOT EDIT BELOW THIS LINE #################################

# http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/11/check-for-admin-credentials-in-a-powershell-script.aspx 
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")){
    Write-Warning "You do not have the Admin rights neccessary to run this script!`nPlease re-run this script as an Administrator!"

# http://webcache.googleusercontent.com/search?q=cache:FjmfLRRqNb4J:https://fortheloveofcode.wordpress.com/2008/06/08/what-no-hkcr-in-powershell/+&cd=1&hl=en&ct=clnk&gl=dk
New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT

if($privacySettings -eq $true){
# Disable Cortana
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Windows Search' -Name AllowCortana -PropertyType DWORD -Value 0 -ErrorAction SilentlyContinue

# Disable Data Logging Services
Get-Service diagtrack,dmwappushservice,RetailDemo | Stop-Service -PassThru | Set-Service -StartupType disabled
New-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection -Name AllowTelemetry -PropertyType DWORD -Value 0 -Force
New-ItemProperty -Path HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Policies\DataCollection -Name AllowTelemetry -PropertyType DWORD -Value 0 -Force

# Disable relevant scheduled tasks
schtasks /change /TN "\Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" /DISABLE
schtasks /change /TN "\Microsoft\Windows\Application Experience\ProgramDataUpdater" /DISABLE
schtasks /change /TN "\Microsoft\Windows\Customer Experience Improvement Program\Consolidator" /DISABLE
schtasks /change /TN "\Microsoft\Windows\Customer Experience Improvement Program\KernelCeipTask" /DISABLE
schtasks /change /TN "\Microsoft\Windows\Customer Experience Improvement Program\UsbCeip" /DISABLE

# Erase the contents of AutoLogger-Diagtrack-Listener.etl
echo "" > C:\ProgramData\Microsoft\Diagnosis\ETLLogs\AutoLogger\AutoLogger-Diagtrack-Listener.etl

# Edit Hosts File
# http://www.dslreports.com/forum/r30222844-Stop-Windows-10-From-Spying-On-You-36-DNS-Addresses-to-host-file
$hostsPath = "$env:windir\System32\drivers\etc\hosts"
$hosts = get-content $hostsPath
[array]$urls = @(

foreach($url in $urls){
    $hostLine = ' '+$url

    if ($hosts -notcontains $hostLine){
        $newHosts = $hosts+$hostLine
        $newHosts | Out-File $hostsPath -Force

# WiFi Sense: HotSpot Sharing: Disable
Set-ItemProperty -Path HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowWiFiHotSpotReporting -Name value -Type DWORD -Value 0

# WiFi Sense: Shared HotSpot Auto-Connect: Disable
Set-ItemProperty -Path HKLM:\Software\Microsoft\PolicyManager\default\WiFi\AllowAutoConnectToWiFiSenseHotspots -Name value -Type DWORD -Value 0

# Start Menu: Disable Bing Search Results
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search -Name BingSearchEnabled -Type DWORD -Value 0

# Privacy: Disable Edge suggestions
Set-ItemProperty -Path HKL:\SOFTWARE\Policies\Microsoft\MicrosoftEdge\SearchScopes -Name ShowSearchSuggestionsGlobal -Type DWORD -Value 0

# Privacy: Let apps use my advertising ID: Disable
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AdvertisingInfo -Name Enabled -Type DWORD -Value 0

# Privacy: SmartScreen Filter for Store Apps: Disable
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\AppHost -Name EnableWebContentEvaluation -Type DWORD -Value 0

if($removeSoftware -eq $true){
# Uninstall OneDrive
Stop-Process -ProcessName *OneDrive*
if(Test-Path "$env:windir\SysWOW64\OneDriveSetup.exe" -eq $true){Start-Process "$env:windir\SysWOW64\OneDriveSetup.exe" -ArgumentList '/uninstall' -Wait}
else{Start-Process "$env:windir\System32\OneDriveSetup.exe" -ArgumentList '/uninstall' -Wait}
Stop-Process -ProcessName *OneDrive* 

Remove-Item "%USERPROFILE%\OneDrive" -Recurse -Force
Remove-Item "C:\OneDriveTemp" -Recurse -Force
Remove-Item "%LOCALAPPDATA%\Microsoft\OneDrive" -Recurse -Force
Remove-Item "%PROGRAMDATA%\Microsoft OneDrive" -Recurse -Force

# Remove Cortana
Get-Process -Name *cortana* | Stop-Process
Get-AppxPackage -AllUsers | ? {$_.Name -match 'Cortana'} | Remove-AppxPackage -ErrorAction SilentlyContinue

#region Windows 10 Metro App Removals
# Be gone, heathen!
Get-AppxPackage king.com.CandyCrushSaga | Remove-AppxPackage

# Bing Weather, News, Sports, and Finance (Money):
Get-AppxPackage Microsoft.BingWeather | Remove-AppxPackage
Get-AppxPackage Microsoft.BingNews | Remove-AppxPackage
Get-AppxPackage Microsoft.BingSports | Remove-AppxPackage
Get-AppxPackage Microsoft.BingFinance | Remove-AppxPackage

# Xbox:
Get-AppxPackage Microsoft.XboxApp | Remove-AppxPackage

# Windows Phone Companion
Get-AppxPackage Microsoft.WindowsPhone | Remove-AppxPackage

# Solitaire Collection
Get-AppxPackage Microsoft.MicrosoftSolitaireCollection | Remove-AppxPackage

# People
Get-AppxPackage Microsoft.People | Remove-AppxPackage

# Groove Music
Get-AppxPackage Microsoft.ZuneMusic | Remove-AppxPackage

# Movies & TV
Get-AppxPackage Microsoft.ZuneVideo | Remove-AppxPackage

# OneNote
Get-AppxPackage Microsoft.Office.OneNote | Remove-AppxPackage

# Photos
Get-AppxPackage Microsoft.Windows.Photos | Remove-AppxPackage

# Sound Recorder
Get-AppxPackage Microsoft.WindowsSoundRecorder | Remove-AppxPackage

# Mail & Calendar
Get-AppxPackage microsoft.windowscommunicationsapps | Remove-AppxPackage

# Skype (Metro version)
Get-AppxPackage Microsoft.SkypeApp | Remove-AppxPackage


if($windowsUpdates -eq $true){
# Change Windows Updates to "Notify to schedule restart"
# https://social.technet.microsoft.com/Forums/en-US/b8bf6607-99a0-441b-ab5f-f699ead7a56f/how-to-stop-windows-10-from-automatically-restarting?forum=WinPreview2014Feedback
Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update' -Name AUOptions -Type DWORD -Value 4

# http://www.download3k.com/articles/How-to-Configure-Windows-Updates-in-Windows-10-01365
New-Item -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows -Name WindowsUpdate
New-Item -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate -Name AU 
New-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU -Name AUOptions -Type DWORD -Value 4 -Force

# Disable P2P Update downloads outside of local network
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config -Name DODownloadMode -Type DWORD -Value 1
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization -Name SystemSettingsDownloadMode -Type DWORD -Value 3

# To disable P2P update downloads completely:
#Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config -Name DODownloadMode -Type DWORD -Value 0

if($UIsettings -eq $true){
# Change Explorer home screen back to "This PC"
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name LaunchTo -Type DWORD -Value 1

# Disable Quick Access: Recent Files
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer -Name ShowRecent -Type DWORD -Value 0

# Disable Quick Access: Frequent Folders
Set-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer -Name ShowFrequent -Type DWORD -Value 0

# Disable the Lock Screen (the one before password prompt - to prevent dropping the first character)
If (-Not (Test-Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\Personalization)) {New-Item -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows -Name Personalization | Out-Null}
Set-ItemProperty -Path HKLM:\SOFTWARE\Policies\Microsoft\Windows\Personalization -Name NoLockScreen -Type DWORD -Value 1

# Use the Windows 7-8.1 Style Volume Mixer
If (-Not (Test-Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MTCUVC")) {New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name MTCUVC | Out-Null}
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MTCUVC" -Name EnableMtcUvc -Type DWORD -Value 0

# Remove folders from MyPC
# https://pricklytech.wordpress.com/2013/10/17/windows-8-1-x64-removing-the-folders-from-file-explorer/
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{1CF1260C-4DD0-4ebb-811F-33C572699FDE}" -Force # Music
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{374DE290-123F-4565-9164-39C4925E467B}" -Force # Downloads
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{3ADD1653-EB32-4cb0-BBD7-DFA0ABB5ACCA}" -Force # Pictures
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{A0953C92-50DC-43bf-BE83-3742FED03C9C}" -Force # Videos
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{A8CDFF1C-4878-43be-B5FD-F8091C1C60D0}" -Force # Documents

Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{088e3905-0323-4b02-9826-5d99428e115f}" -Force # Downloads 
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{24ad3ad4-a569-4530-98e1-ab02f9417aa8}" -Force # Pictures
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{3dfdf296-dbec-4fb4-81d1-6a3438bcf4de}" -Force # Music
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{B4BFCC3A-DB2C-424C-B029-7FE99A87C641}" -Force # Desktop
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{d3162b92-9365-467a-956b-92703aca08af}" -Force # Documents
Remove-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\MyComputer\NameSpace\{f86fa3ab-70d2-4fc7-9c99-fcbf05467f3a}" -Force # Videos
# Remove OneDrive from the Explorer Side Panel.
Remove-Item "HKCR:\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" -Force -Recurse
Remove-Item "HKCR:\Wow6432Node\CLSID\{018D5C66-4533-4307-9B53-224DE2ED1FE6}" -Force -Recurse

# Remove Compressed file/folder
Remove-Item "HKCR:\CABFolder\CLSID" -Force -Recurse
Remove-Item "HKCR:\CompressedFolder\CLSID" -Force -Recurse
Remove-Item "HKCR:\SystemFileAssociations\.cab\CLSID" -Force -Recurse
Remove-Item "HKCR:\SystemFileAssociations\.zip\CLSID" -Force -Recurse

# Explorer: Show all folders
New-ItemProperty -path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name NavPaneShowAllFolders -PropertyType DWORD -Value 1

# Explorer: Show file extensions
New-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name HideFileExt -PropertyType DWORD -Value 0

# Explorer: Show hidden files
New-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name Hidden -PropertyType DWORD -Value 1

# Taskbar: Show all icons in taskbar
New-ItemProperty -Path HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer -Name EnableAutoTray -PropertyType DWORD -Value 0
New-ItemProperty -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name NavPaneShowAllFolders -PropertyType DWORD -Value 1

# Taskbar: Hide Task View Button
New-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced -Name ShowTaskViewButton -PropertyType DWORD -Value 0

# Taskbar: Hide Search
New-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Search -Name SearchboxTaskbarMode -PropertyType DWORD -Value 0

# Bring back old Windows Update control panel app
# http://answers.microsoft.com/en-us/insider/forum/insider_wintp-insider_update/need-the-old-windows-update-not-the-new-windows/35bc83a7-3aa9-4408-b189-4aa2777e4e11
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX -Name IsConvergedUpdateStackEnabled -Value 0 -Force
Set-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings -Name UxOption -Value 0 -Force

# Titlebar: Enable accent colors
# http://www.intowindows.com/how-to-change-title-bar-color-in-windows-10/ 
Copy-Item -Path $env:windir\Resources\Themes\aero -Recurse -Destination $env:windir\Resources\Themes\windows -Force -ErrorAction SilentlyContinue
Get-ChildItem -Path $env:windir\Resources\Themes\windows -Filter "aero.msstyles*" -Recurse | Rename-Item -NewName {$_.name -replace 'aero','windows' }
(Get-Content $env:windir\Resources\Themes\aero.theme).Replace('Path=%ResourceDir%\Themes\Aero\Aero.msstyles', 'Path=%ResourceDir%\Themes\windows\windows.msstyles') | Set-Content $env:TEMP\windows.theme
Start-Process $env:TEMP\windows.theme -Wait
(New-Object -comObject Shell.Application).Windows() | where-object {$_.LocationName -eq "Personalization"} | foreach-object {$_.quit()}
Remove-Item $env:TEMP\windows.theme

# Finishing touches
Write-Host "Please make sure you do the following as well:`nSelect Never in the first box, and Basic in the second box"
start ms-settings:privacy-feedback

CRM Server – Scripted installation

Yet another nice script from Mads Hjort Larsen.
I simply hadn’t found any automated installation of CRM server, including prerequisites SQL Reporting Services native mode and Watson components, so we decided to work this out. The script requires both SQL installation media as well as CRM Server media.

Script runtime is long, approximately 1 hour. That is just how long it takes to install all components. For reference, here is a video of a script run.

NB: For some reason the parser is unable to parse to full script below.
Copy into Powershell ISE or similar will yield a fully color coded script.
NBB: This script has severe issues against named instances of SQL. We will issue an update once we have tested this.

Set-Location $PSScriptRoot

#region Variables
$CRMgroupOU = '<CRM OU>' # Specifies the Active Directory organizational unit (OU) where the security groups will be created, for example, <OU> OU=CRM, DC=MySubDomain, DC=MyDomain, DC=com</OU>.
$SQLserver = '<SQL SERVER>'

$SQLmedia = 'D:' # Location of SQL server install media
$CRMmedia = 'E:' # Location of CRM server install media

$CRMupdateDir = "$PSScriptRoot\updates" # Directory that SERVER, ROUTER, SRS and MUI update files will be downloaded to.

$CRMSetupUser = '<CRM Setup User>' # Local Admin on CRM Server, Local Admin on SQL Server, Delegate Full Control on CRM Group OU
$CRMSetupUserPassword = '<CRM Setup User Password>'

$svcCRMApp = '<CRM AppPool account>' # Specifies the service account used to run the Microsoft Dynamics CRM Unzip Service and ASP.NET AppPool application pool identity.
$svcCRMAppPassword = '<CRM AppPool account password>'

$svcCRMDeploy = '<CRM Deployment account>' # Specifies the service account to use for the Deployment Web service.
$svcCRMDeployPassword = '<CRM Deployment account password>'

$svcCRMSandbox = '<CRM Sandbox account>' # Specifies the service account to use for the Sandbox Processing service.
$svcCRMSandboxPassword = '<CRM Sandbox account password>'

$svcCRMVSS = '<CRM VSS account>' # Specifies the service account to use for the Microsoft Dynamics CRM VSS Writer service.
$svcCRMVSSPassword = '<CRM VSS account password>'

$svcCRMAsync = '<CRM aSynch account>' # Specifies the service account to use for the asynchronous processing services.
$svcCRMAsyncPassword = '<CRM aSynch account password>'

$svcCRMMonitor = '<CRM Monitor account>' # Specifies the service account to use for the Microsoft Dynamics CRM Monitoring service.
$svcCRMMonitorPassword = '<CRM Monitor account password>'

$svcCRMEmailRouter = '<CRM Email router account>' # Specifies the service account to use for the Microsoft Dynamics CRM Email Router service.
$svcCRMEmailRouterPassword = 'CRM Email router account password>'

$RSappPoolAccount = '<SQL Reporting Services account>'
$RSappPoolAccountPassword = '<SQL Reporting Services account password>'

$RSdbname = $env:COMPUTERNAME+'_SQL_Reporting' # SQL Reporting Services database name.
$ReportingServicesURL = $env:COMPUTERNAME+":80" # SQL Reporting services URL (name and port)

$RSemailServer = "smtp.mycompany.com"
$RSemailAddress = "reporting.services@mycompany.co.uk"

$DBinstance = '<SQL Client Alias>' # Should be a SQL Client connection alias (Not SQL server alias).
$RSinstance = '' # If this value is left blank "MSSQLSERVER" will be used

# https://technet.microsoft.com/en-us/library/hh699830.aspx
$patchUpdate = 'True' # Determines the behavior of the update Microsoft Dynamics CRM Server Setup technology. This feature lets Setup perform a one-time search for, and if applicable, download and apply the latest installation files for Microsoft Dynamics CRM.
$patchPath = '' # \\ServerName\ShareName\patchfile.msp

$licenseKey = '<License Key>' # Specifies the product key for this deployment. The configuration file can contain only one Microsoft Dynamics CRM product key.
$databaseCreate = 'true' # Values for this parameter are either true or false. True causes Setup to create a new Microsoft Dynamics CRM configuration database. False causes Setup to connect to an existing Microsoft Dynamics CRM configuration database.
$reportingUrl = "http://$env:COMPUTERNAME/ReportServer" # Specifies the URL of the Report Server.
$Collation = 'Latin1_General_CI_AI' # Specifies the SQL Server database collation name to use for the organization database. The default collation depends on the language of Microsoft Dynamics CRM Server that you’re installing, for example, Latin1_General_Cl_Al, which is the default collation for English (US) language deployments.

# After Setup is complete, you cannot change the base ISO currency code. However, you can change the base-currency name, base-currency symbol, and base-currency precision.
$currencycode="<ISO Currency code>" # Specifies the ISO three-letter currency-code, display name, and symbol to use for the base currency. For example, if you want to use U.S. dollars as the base currency, use isocurrencycode="USD". You must use a valid ISO currency description for the isocurrencycode attribute.
$currencyname="<Currency Name>" # You must also specify the currency-name and currency-symbol display names for the ISO base currency. For example, if the ISO currency code is USD, the currency name should be "US Dollar" and the currency symbol should be "$". However, you can use any string that you want for these attributes.
$currencysymbol="<Currency Symbol>" 
$currencyprecision="<Currency Precision>" # You must specify the precision for the base currency that you specified in the currencycode attribute. Valid values depend on the type of currency that you specify. For example, USD valid values are 1 – 9 and the default value is 2.

$displayName = '<CRM Display Name>' # Specifies the long name of your organization. The name can be up to 250 characters long and extended characters are supported.
$uniqueName = '<Organizational Name>' # Specifies the name of your organization in the URL that users will use to access the deployment. There is a 30 character limit. Extended characters or spaces are not allowed. If you don’t specify this element or leave the value blank, Setup will generate a short name based on the <Organization> element value.

$createNewWebsite = 'True' # Specifies the website to be used for Microsoft Dynamics CRM Server. Use Create="true" to create a new Microsoft Dynamics CRM website and leave the value $webSitePath blank.
$websitePort = '<CRM Port>' # Use port="TCPportnumber", where TCPportnumber is a valid and available TCP port number, to specify the port for connecting to the Microsoft Dynamics CRM Server application. If left blank, the port number that will be used is 5555. If $createNewWebsite="false", the port attribute is ignored.
$webSitePath = '' # Only needed if $createNewWebsite = 'false'

$SQMoptin = 'False' # Specifies whether you will participate in the Customer Experience Improvement Program.
$MUoptin = 'False' # Specifies whether to use Microsoft Update to download and install updates to Microsoft Dynamics CRM Server and other installed applications. After the installation is completed, this feature helps keep your computer up-to-date on an ongoing basis.

$ifdsettings = 'False' # This option should only be used for Internet-facing deployment. Set enabled = "true" to notify Microsoft Dynamics CRM server Setup to configure the deployment for Internet access. If the <ifdsettings> element is not specified, the enabled attribute value is set to false.
$internalnetworkaddress = '' # IP address and subnet mask, such as This is the internal IP address and the associated subnet mask of the subnet where your internal users reside. The subnets you enter here will be for the computers that you want to be considered as internal and you do not want the users to login through the IFD environment when they are on these subnets. To enter multiple subnets use a comma to separate the values in the configuration file Note: If you leave this element blank, all communication to the Microsoft Dynamics CRM server will be considered as internal and users will default to windows authentication when hitting the Microsoft Dynamics CRM website.
$rootdomainscheme = 'http' # Must be https, which will use secure sockets layer (SSL), or http, which will use the nonsecure HTTP protocol. Note: Setup does not require SSL on the Web site where Microsoft Dynamics CRM is installed. We strongly recommend that you specify the https value in the rootdomainscheme element. In addition, after Setup is complete, to help protect information that is transmitted between users and Microsoft Dynamics CRM Server, we recommend that you configure the Web site to require SSL. 
$sdkrootdomain = 'api.contoso.com' # Specifies the domain name that will be used for applications that use the methods described in the Microsoft Dynamics CRM 4.0 Software Development Kit (SDK). The value that is set here will be prefixed by your unique organization name to form the URL so you only need to put in the domain.com
$webapplicationrootdomain = 'app.contoso.com' # Specifies the domain name that will be used for the Microsoft Dynamics CRM Web application and Microsoft Dynamics CRM for Outlook. The value that is set here will be prefixed by your unique organization name to form the URL so you only need to put in the domain.com 
$discoveryrootdomain = 'disc.contoso.com' # The root domain for the discovery Web service.

$ExchangeServerName = '' # Specifies the Microsoft Exchange Server computer or POP3 that will be used by the Email Router to route incoming email messages. If not specified and later the Email Router is used in the deployment, the computer must be added to the PrivUserGroup security group.
$nonHTTPS = 'True' # If you do not want to use HTTPS, set this to true - see https://msdn.microsoft.com/en-us/library/hh550122(v=crm.6).aspx for more info.

   $Server = 'http://download.microsoft.com/download/5/F/4/5F43956F-E1CF-4F15-96BE-967AF29E2005/CRM2015-Server-KB3010990-ENU-amd64.exe'
   $Router = 'http://download.microsoft.com/download/5/F/4/5F43956F-E1CF-4F15-96BE-967AF29E2005/CRM2015-Router-KB3010990-ENU-amd64.exe'
      $SRS = 'http://download.microsoft.com/download/5/F/4/5F43956F-E1CF-4F15-96BE-967AF29E2005/CRM2015-Srs-KB3010990-ENU-amd64.exe'
   $MUIENU = 'http://download.microsoft.com/download/5/F/4/5F43956F-E1CF-4F15-96BE-967AF29E2005/CRM2015-Mui-KB3010990-ENU-amd64.exe'
   $MUIDAN = 'http://download.microsoft.com/download/A/C/5/AC560071-42FF-44C0-AEE7-848FF99F74D9/CRM2015-Mui-DAN-amd64.exe'
$MUIDANUPD = 'http://download.microsoft.com/download/A/A/0/AA01E7CA-9120-48E4-8637-FFD8AD5E9C55/CRM2015-Mui-KB3056327-DAN-amd64.exe'

# It should not be neccessary to edit below this line ------------------- πŸ™‚ #

$SQLinstallFile = $SQLmedia+'\Setup.exe'
$CRMinstallFile = $CRMmedia+'\Server\amd64\SetupServer.exe' # Location of SetupServer.exe
$SRSInstallFile = $CRMmedia+'\Server\amd64\SrsDataConnector\SetupSrsDataConnector.exe'
$EmailRouterInstallFile = $CRMmedia+'\EmailRouter\amd64\SetupEmailRouter.exe' # Location of Email Router setup file.
$ADserver = ([ADSI]”LDAP://RootDSE”).dnsHostName

function Add-Clock {
    $code = { 
    $start = Get-Date
    do {
        $now = Get-Date
        $diff = $now-$start
        $title = ("$diff").Split('.')[0].ToString()
        [System.Console]::Title = "Approx. time elapsed: "+$title
        Start-Sleep -Seconds 1
        } while ($true)

$ps = [PowerShell]::Create()
$null = $ps.AddScript($code)

if (!(Test-Path placeholder.tmp)) {
Add-Clock | Out-Null
Write-Host ''
Write-Host ' β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—' -ForegroundColor Green
Write-Host ' β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•‘β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β•β•β•' -ForegroundColor Green
Write-Host ' β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—' -ForegroundColor Green
Write-Host ' β–ˆβ–ˆβ•”β•β•β•β• β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•  β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•”β•β•β•  β–ˆβ–ˆβ•‘β–„β–„ β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ•β•β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•”β•β•β•  β•šβ•β•β•β•β–ˆβ–ˆβ•‘' -ForegroundColor Green
Write-Host ' β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘' -ForegroundColor Green
Write-Host ' β•šβ•β•     β•šβ•β•  β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•  β•šβ•β•β•šβ•β•β•β•β•β•β• β•šβ•β•β–€β–€β•β•  β•šβ•β•β•β•β•β• β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•   β•šβ•β•   β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•' -ForegroundColor Green
Write-Host ''

Write-Host 'Verifying SQL server setup...'
$Fulltext = Get-Service -ComputerName $sqlServer -DisplayName "SQL Full-Text*"
if ($Fulltext -eq $null){Write-Host "Full Text Search is not installed on $sqlServer" -ForegroundColor Red}
else{Write-Host $Fulltext.DisplayName "found on $SQLserver"}

$SQLAgent = Get-Service -ComputerName $sqlServer -DisplayName "SQL Server Agent*"
if ($SQLAgent -eq $null){Write-Host "SQL Agent is not installed on $sqlServer" -ForegroundColor Red}
else{Write-Host $SQLAgent.DisplayName "found on $SQLserver";Invoke-Command -ComputerName $sqlServer -ScriptBlock {Start-Service -Name SQLSERVERAGENT}}

if ($Fulltext -eq $null -OR $SQLAgent -eq $null){Exit}

New-Item placeholder.tmp -Type File -Force | Out-Null

#region HostsFileAndSQLAlias
Write-Host "`nAdding to Hosts file: " -NoNewline
$SQLServerIP = (Test-Connection -ComputerName $SQLserver -Count 1).IPV4Address.IPAddressToString

$hostsPath = "$env:windir\System32\drivers\etc\hosts"
$hosts = get-content $hostsPath
$hostLine = $SQLServerIP +' '+ $DBinstance
Write-Host $hostLine

if ($hosts -notcontains $hostLine){
    $newHosts = $hosts+$hostLine
    $newHosts | Out-File $hostsPath -Force

# Check SQL alias
Write-Host "`nCreating TCP/IP Aliases`n"
Start-Process $env:windir\System32\cliconfg.exe
Start-Process $env:windir\sysWOW64\cliconfg.exe
Sleep 1
Stop-Process -Name cliconfg

# These are the two Registry locations for the SQL Alias locations
$x86 = "HKLM:\Software\Microsoft\MSSQLServer\Client\ConnectTo"
$x64 = "HKLM:\Software\Wow6432Node\Microsoft\MSSQLServer\Client\ConnectTo"
# Test to see if the ConnectTo key already exists, and create it if it doesn't.
if ((test-path -path $x86) -ne $True){New-Item $x86 | Out-Null}
if ((test-path -path $x64) -ne $True){New-Item $x64 | Out-Null}
$TCPAlias = "DBMSSOCN," + $SQLserver
New-ItemProperty -Path $x86 -Name $DBinstance -PropertyType String -Value $TCPAlias -Force | Out-Null
New-ItemProperty -Path $x64 -Name $DBinstance -PropertyType String -Value $TCPAlias -Force | Out-Null

#region CreateUsers
[ScriptBlock]$ScriptBlock = { 

    function AddUser ($user,$pass){
        if(!(Get-ADUser -Filter {sAMAccountname -eq $user})) {
            "Creating $user"
            New-ADUser -Name $user -AccountPassword (ConvertTo-SecureString -AsPlainText $pass -Force) -Enabled $true -Path $CRMgroupOU
        else{"User $user already exists."}

    if(!(Get-ADOrganizationalUnit -Filter {DistinguishedName -like $CRMgroupOU})){
        "Creating OU ($CRMgroupOU)"
        New-ADOrganizationalUnit -Name $CRMgroupOU.Split(',')[0].Split('=')[1] -Path ($CRMgroupOU.Split(',')[1..($CRMgroupOU.SPlit(',').Count)] -join ',')
    else{"OU ($CRMgroupOU) already exists."}
    Write-Host "`nCreating accounts:"
    AddUser $CRMSetupUser $CRMSetupUserPassword
    AddUser $svcCRMApp $svcCRMAppPassword
    AddUser $svcCRMDeploy $svcCRMDeployPassword
    AddUser $svcCRMSandbox $svcCRMSandboxPassword
    AddUser $svcCRMVSS $svcCRMVSSPassword
    AddUser $svcCRMAsync $svcCRMAsyncPassword
    AddUser $svcCRMMonitor $svcCRMMonitorPassword
    AddUser $svcCRMEmailRouter $svcCRMEmailRouterPassword
    AddUser $RSappPoolAccount $RSappPoolAccountPassword

Invoke-Command -ComputerName $ADserver -ScriptBlock $ScriptBlock -ArgumentList $CRMgroupOU, $CRMSetupUser, $CRMSetupUserPassword, $svcCRMApp, $svcCRMAppPassword, $svcCRMDeploy, $svcCRMDeployPassword, $svcCRMSandbox, $svcCRMSandboxPassword, $svcCRMVSS, $svcCRMVSSPassword, $svcCRMAsync, $svcCRMAsyncPassword, $svcCRMMonitor, $svcCRMMonitorPassword, $svcCRMEmailRouter, $svcCRMEmailRouterPassword, $RSappPoolAccount, $RSappPoolAccountPassword

#region LogonAsService
# http://anexinetisg.blogspot.dk/2014/02/grant-users-log-on-as-service-right-via.html
function Grant-LogOnAsService{
    [string[]] $users
    #Get list of currently used SIDs 
    secedit /export /cfg tempexport.inf | Out-Null
    $curSIDs = Select-String .\tempexport.inf -Pattern "SeServiceLogonRight" 
    $Sids = $curSIDs.line 
    $sidstring = ""
    foreach($user in $users){
        $objUser = New-Object System.Security.Principal.NTAccount($user)
        $strSID = $objUser.Translate([System.Security.Principal.SecurityIdentifier])
        if(!$Sids.Contains($strSID) -and !$sids.Contains($user)){
            $sidstring += ",*$strSID"
        $newSids = $sids + $sidstring
        Write-Host "`nNew Sids: " -NoNewline
        $tempinf = Get-Content tempexport.inf
        $tempinf = $tempinf.Replace($Sids,$newSids)
        Add-Content -Path tempimport.inf -Value $tempinf
        secedit /import /db secedit.sdb /cfg ".\tempimport.inf" | Out-Null
        secedit /configure /db secedit.sdb | Out-Null
        gpupdate /force | Out-Null
        Write-Host "`nNo new sids"
    Remove-Item ".\tempimport.inf" -Force -ErrorAction SilentlyContinue
    Remove-Item ".\secedit.sdb" -Force -ErrorAction SilentlyContinue
    Remove-Item ".\tempexport.inf" -Force -ErrorAction SilentlyContinue

Grant-LogOnAsService -users $svcCRMApp, $svcCRMDeploy, $svcCRMSandbox, $svcCRMVSS, $svcCRMAsync, $svcCRMMonitor

#region Add-DomainUserToLocalGroup
# http://blogs.technet.com/b/heyscriptingguy/archive/2010/08/19/use-powershell-to-add-domain-users-to-a-local-group.aspx
function Add-DomainUserToLocalGroup { 
    $de = [ADSI]"WinNT://$computer/$Group,group" 

Add-DomainUserToLocalGroup -user $CRMSetupUser -group 'Administrators' -domain $env:USERDOMAIN -computer $env:COMPUTERNAME
Add-DomainUserToLocalGroup -user $CRMSetupUser -group 'Administrators' -domain $env:USERDOMAIN -computer $SQLserver

Add-DomainUserToLocalGroup -user $svcCRMApp -group 'Administrators' -domain $env:USERDOMAIN -computer $env:COMPUTERNAME
Add-DomainUserToLocalGroup -user $svcCRMApp -group 'Performance Log Users' -domain $env:USERDOMAIN -computer $env:COMPUTERNAME

Add-DomainUserToLocalGroup -user $svcCRMDeploy -group 'Administrators' -domain $env:USERDOMAIN -computer $env:COMPUTERNAME
Add-DomainUserToLocalGroup -user $svcCRMDeploy -group 'Administrators' -domain $env:USERDOMAIN -computer $SQLserver

Add-DomainUserToLocalGroup -user $svcCRMAsync -group 'Performance Log Users' -domain $env:USERDOMAIN -computer $env:COMPUTERNAME

# Delegate Full Control on CRM Group OU
$ScriptBlock = [Scriptblock]::Create('dsacls "'+$CRMgroupOU+'"'+" /G $env:USERDOMAIN\$CRMSetupUser"+':GA /I:T')
Invoke-Command -ComputerName $ADserver -ScriptBlock $ScriptBlock | Out-Null

# Grant $CRMsetupUser SysAdm rights on the SQL server
$ScriptBlock = {
    Import-Module -Name SQLPS -DisableNameChecking
    Add-Type -AssemblyName "Microsoft.SqlServer.Smo, Version=, Culture=neutral, PublicKeyToken=89845dcd8080cc91"
    $smo = New-Object Microsoft.SqlServer.Management.Smo.Server $env:COMPUTERNAME
    $sqlUser = New-Object -TypeName Microsoft.SqlServer.Management.Smo.Login -ArgumentList $smo,"$env:USERDOMAIN\$CRMSetupUser"
    $sqlUser.LoginType = 'WindowsUser'
    $sqlUser.PasswordPolicyEnforced = $false
Invoke-Command -ComputerName $SQLserver -ScriptBlock $ScriptBlock -ArgumentList $CRMSetupUser

#region ReportingServices
if ($RSinstance -eq ''){$RSinstance = 'MSSQLSERVER'}

$temp = $WarningPreference
$WarningPreference = 'SilentlyContinue'
Install-WindowsFeature –Name NET-Framework-Core
$WarningPreference = $temp

$ArgumentList = '/ACTION="Install" /FEATURES=RS /RSINSTALLMODE="FilesOnlyMode" /INSTANCENAME="'+$RSinstance+'" /INSTANCEID="'+$RSinstance+'" /ENU="True" /QUIETSIMPLE="True" /IACCEPTSQLSERVERLICENSETERMS /UpdateEnabled="True" /UpdateSource="MU" /ERRORREPORTING="False" /SQMREPORTING="'+$SQMoptin+'" /RSSVCACCOUNT='+$env:USERDOMAIN+'\'+$RSappPoolAccount+' /RSSVCPASSWORD='+$RSappPoolAccountPassword+' /RSSVCSTARTUPTYPE="Automatic"'
Start-Process $SQLinstallFile -ArgumentList $ArgumentList -Wait

Write-Host "`nGenerating Reporting Services configuration databases..."

$s = New-Object Management.ManagementScope("\\localhost\root\Microsoft\SqlServer\ReportServer\RS_$RSinstance\v12\admin")

$sc = New-Object Management.ManagementClass("\\localhost\root\Microsoft\SqlServer\ReportServer\RS_$RSinstance\v12\admin:MSReportServer_ConfigurationSetting")

$insts = $sc.GetInstances()
foreach ($o in $insts) { $inst = $o; }

# Set Virtual Directories
$inst.RemoveURL("ReportServerWebService", "http://$ReportingServicesURL", 1033) | Out-Null
$inst.RemoveURL("ReportManager", "http://$ReportingServicesURL", 1033) | Out-Null

$inst.SetVirtualDirectory("ReportServerWebService", "ReportServer", 1033) | Out-Null
$inst.SetVirtualDirectory("ReportManager", "ReportManager", 1033) | Out-Null

$inst.ReserveURL("ReportServerWebService", "http://$ReportingServicesURL", 1033) | Out-Null
$inst.ReserveURL("ReportManager", "http://$ReportingServicesURL", 1033) | Out-Null

# Create Reporting Services Database
$script = $inst.GenerateDatabaseCreationScript($RSdbname, 1033, $false)

[scriptblock]$scriptBlock = {
    $script.Script | Out-File rs.sql
    sqlcmd -i rs.sql
    Remove-Item rs.sql
Invoke-Command -ComputerName $sqlServer -ScriptBlock $scriptBlock -ArgumentList $script,$DBinstance | Out-Null

$script = $inst.GenerateDatabaseRightsScript("$env:USERDOMAIN\$RSappPoolAccount", $RSdbname, $false, $true)

[scriptblock]$scriptBlock = {
    $script.Script | Out-File rs.sql
    sqlcmd -i rs.sql
    Remove-Item rs.sql
Invoke-Command -ComputerName $sqlServer -ScriptBlock $scriptBlock -ArgumentList $script,$DBinstance | Out-Null

$inst.SetDatabaseConnection($DBinstance, $RSdbname, 2, "", "") | Out-Null
$inst.SetWindowsServiceIdentity($false, "$env:USERDOMAIN\$RSappPoolAccount", $RSappPoolAccountPassword) | Out-Null
#$inst.SetUnattendedExecutionAccount("<domain\user>", "<password>") | Out-Null
$inst.SetServiceState($true, $true, $true) | Out-Null
$inst.SetEmailConfiguration($true, $RSemailServer, $RSemailAddress) | Out-Null

#region CRMserverPreReqs
Write-Host "`nInstalling CRM server prereqs:"
Write-Host "1of6 - Microsoft .NET Framework 4.5.2"
$file = gci ($CRMmedia+'\Redist\dotNETFX')
Start-Process $file.FullName -ArgumentList '/PASSIVE /NORESTART' -Wait

Write-Host "2of6 - Microsoft Application Error Reporting" 
$file = gci ($CRMmedia+'\Server\amd64\DW')
Start-Process $file.FullName -ArgumentList 'APPGUID=91710409-8000-11D3-8CFE-0150048383C9 /PASSIVE /NORESTART' -Wait

Write-Host "3of6 - SQL Native Client" 
$file = gci ($CRMmedia+'\Redist\SQLNativeClient')
Start-Process $file.FullName -ArgumentList '/PASSIVE /NORESTART' -Wait

Write-Host "4of6 - SQL Clr types" 
$file = gci ($CRMmedia+'\Redist\SQLSystemCLRTypes\*64*')
Start-Process $file.FullName -ArgumentList '/PASSIVE /NORESTART' -Wait

Write-Host "5of6 - SQL Server Management Objects" 
$file = gci ($CRMmedia+'\Redist\SQLSharedManagementObjects')
Start-Process $file.FullName -ArgumentList '/PASSIVE /NORESTART' -Wait

Write-Host "6of6 - Microsoft SQL Reporting Service Report Viewer Control" 
$file = gci ($CRMmedia+'\Redist\ReportViewer')
Start-Process $file.FullName -ArgumentList '/PASSIVE /NORESTART' -Wait

#region AutoRun&AutoLogon
New-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce -Name "Test" -Value ("$pshome\powershell.exe -Command `"& `'$PSCommandPath`'`"") | Out-Null

Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName -Value "$env:USERDOMAIN\$CRMSetupUser"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultPassword -Value "$CRMSetupUserPassword"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -Value "1"
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name ForceAutoLogon -Value "1"

Write-Host "`nRebooting..."
Add-Clock | Out-Null
#region CRMinstall
Write-Host ''
Write-Host '  β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ–ˆβ•—    β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ•—     β–ˆβ–ˆβ•—     ' -ForegroundColor Green
Write-Host ' β–ˆβ–ˆβ•”β•β•β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ•— β–ˆβ–ˆβ–ˆβ–ˆβ•‘    β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ•—  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β•β•β•β•β•β•šβ•β•β–ˆβ–ˆβ•”β•β•β•β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘     ' -ForegroundColor Green
Write-Host ' β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•”β–ˆβ–ˆβ–ˆβ–ˆβ•”β–ˆβ–ˆβ•‘    β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•”β–ˆβ–ˆβ•— β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘     ' -ForegroundColor Green
Write-Host ' β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•”β•β–ˆβ–ˆβ•‘    β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘β•šβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘β•šβ•β•β•β•β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•”β•β•β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘     β–ˆβ–ˆβ•‘     ' -ForegroundColor Green
Write-Host ' β•šβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ•β• β–ˆβ–ˆβ•‘    β–ˆβ–ˆβ•‘β–ˆβ–ˆβ•‘ β•šβ–ˆβ–ˆβ–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘   β–ˆβ–ˆβ•‘  β–ˆβ–ˆβ•‘β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ•—' -ForegroundColor Green
Write-Host '  β•šβ•β•β•β•β•β•β•šβ•β•  β•šβ•β•β•šβ•β•     β•šβ•β•    β•šβ•β•β•šβ•β•  β•šβ•β•β•β•β•šβ•β•β•β•β•β•β•   β•šβ•β•   β•šβ•β•  β•šβ•β•β•šβ•β•β•β•β•β•β•β•šβ•β•β•β•β•β•β•' -ForegroundColor Green
Write-Host ''

$xml = $null
$CRMxmlfile = "$PSScriptRoot\CRMSetupconfig.xml"

Write-Host 'Creating CRM Server XML answer file...'

$xml += '<CRMSetup>';$xml += "`r`n"
$xml += '<Server>';$xml += "`r`n"
$xml += '<Patch update="'+$patchUpdate+'">'+$patchPath+'</Patch>';$xml += "`r`n"
$xml += "<LicenseKey>$licenseKey</LicenseKey>";$xml += "`r`n"
$xml += "<SqlServer>$DBinstance</SqlServer>";$xml += "`r`n"
$xml += '<Database create="'+$databaseCreate+'"/>';$xml += "`r`n"
$xml += '<Reporting URL="'+$reportingUrl+'" />';$xml += "`r`n"
$xml += "<OrganizationCollation>$collation</OrganizationCollation>";$xml += "`r`n"
$xml += '<basecurrency isocurrencycode="'+$currencycode+'" currencyname="'+$currencyname+'" currencysymbol="'+$currencysymbol+'" currencyprecision="'+$currencyprecision+'"/>';$xml += "`r`n"
$xml += "<Organization>$displayName</Organization>";$xml += "`r`n"
$xml += "<OrganizationUniqueName>$uniqueName</OrganizationUniqueName>";$xml += "`r`n"
$xml += "<OU>$CRMgroupOU</OU>";$xml += "`r`n"
$xml += '<WebsiteUrl create="'+$createNewWebsite+'" port="'+$websitePort+'">'+$webSitePath+'</WebsiteUrl>';$xml += "`r`n"
$xml += "<InstallDir>C:\Program Files\Microsoft Dynamics CRM</InstallDir>";$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<CrmServiceAccount type="DomainUser">';$xml += "`r`n"
$xml += "   <ServiceAccountLogin>$env:USERDOMAIN\$svcCRMApp</ServiceAccountLogin>" ;$xml += "`r`n"
$xml += "   <ServiceAccountPassword>$svcCRMAppPassword</ServiceAccountPassword>";$xml += "`r`n"
$xml += '</CrmServiceAccount>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<SandboxServiceAccount type="DomainUser">';$xml += "`r`n"
$xml += "  <ServiceAccountLogin>$env:USERDOMAIN\$svcCRMSandbox</ServiceAccountLogin>";$xml += "`r`n"
$xml += "  <ServiceAccountPassword>$svcCRMSandboxPassword</ServiceAccountPassword>";$xml += "`r`n"
$xml += '</SandboxServiceAccount>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<DeploymentServiceAccount type="DomainUser">';$xml += "`r`n"
$xml += "  <ServiceAccountLogin>$env:USERDOMAIN\$svcCRMDeploy</ServiceAccountLogin>";$xml += "`r`n"
$xml += "  <ServiceAccountPassword>$svcCRMDeployPassword</ServiceAccountPassword>";$xml += "`r`n"
$xml += '</DeploymentServiceAccount>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<AsyncServiceAccount type="DomainUser">';$xml += "`r`n"
$xml += "  <ServiceAccountLogin>$env:USERDOMAIN\$svcCRMAsync</ServiceAccountLogin>";$xml += "`r`n"
$xml += "  <ServiceAccountPassword>$svcCRMAsyncPassword</ServiceAccountPassword>";$xml += "`r`n"
$xml += '</AsyncServiceAccount>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<VSSWriterServiceAccount type="DomainUser">';$xml += "`r`n"
$xml += "  <ServiceAccountLogin>$env:USERDOMAIN\$svcCRMVSS</ServiceAccountLogin>";$xml += "`r`n"
$xml += "  <ServiceAccountPassword>$svcCRMVSSPassword</ServiceAccountPassword>";$xml += "`r`n"
$xml += '</VSSWriterServiceAccount>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<MonitoringServiceAccount type="DomainUser">';$xml += "`r`n"
$xml += "  <ServiceAccountLogin>$env:USERDOMAIN\$svcCRMMonitor</ServiceAccountLogin>";$xml += "`r`n"
$xml += "  <ServiceAccountPassword>$svcCRMMonitorPassword</ServiceAccountPassword>";$xml += "`r`n"
$xml += '</MonitoringServiceAccount>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<SQM optin="'+$SQMoptin+'"/>';$xml += "`r`n"
$xml += '<muoptin optin="'+$MUoptin+'"/>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += '<!-- Settings for IFD installation. May be skipped for intranet-only deployment or to configure IFD later. -->';$xml += "`r`n"
$xml += ' <ifdsettings enabled="'+$ifdsettings+'">';$xml += "`r`n"
$xml += '      <!-- Define what address considered internal, required only if enabled=true -->';$xml += "`r`n"
$xml += '      <internalnetworkaddress>'+$internalnetworkaddress+'</internalnetworkaddress>';$xml += "`r`n"
$xml += '      <!-- Define URLs with IFD authentication, required only if enabled=true -->';$xml += "`r`n"
$xml += '      <rootdomainscheme>'+$rootdomainscheme+'</rootdomainscheme>';$xml += "`r`n"
$xml += '      <sdkrootdomain>'+$sdkrootdomain+'</sdkrootdomain>';$xml += "`r`n"
$xml += '      <webapplicationrootdomain>'+$webapplicationrootdomain+'</webapplicationrootdomain>';$xml += "`r`n"
$xml += '      <discoveryrootdomain>'+$discoveryrootdomain+'</discoveryrootdomain>';$xml += "`r`n"
$xml += ' </ifdsettings>';$xml += "`r`n"
$xml += '';$xml += "`r`n"
$xml += ' <Email>';$xml += "`r`n"
$xml += '  <IncomingExchangeServer name="'+$ExchangeServerName+'"/>';$xml += "`r`n"
$xml += ' </Email>';$xml += "`r`n"
$xml += '<LaunchReportingExtensionsSetup>False</LaunchReportingExtensionsSetup>';$xml += "`r`n"
$xml += ' </Server>';$xml += "`r`n"
$xml += '</CRMSetup>';$xml += "`r`n"

$xml | Out-File $CRMxmlfile -Force

Write-Host "Installing CRM server... pull up a chair, this part could take a while, like 30-40 mins :)`n"
Start-Process $CRMinstallFile -ArgumentList "/Q /config $CRMxmlfile" -Wait
Remove-Item placeholder.tmp

#region SrsDataConnector
$xml = $null
$SRSxmlfile = "$PSScriptRoot\SrsDataConnectorSetupConfig.xml"

Write-Host 'Creating SrsDataConnector XML answer file...'

$xml += '<crmsetup>';$xml += "`r`n"
$xml += '<srsdataconnector>';$xml += "`r`n"
$xml += '<configdbserver>'+$SQLserver+'</configdbserver>';$xml += "`r`n"
$xml += '<autoupdateconfigdb>1</autoupdateconfigdb>';$xml += "`r`n"
$xml += '<reportserverurl>'+$reportingUrl+'</reportserverurl>';$xml += "`r`n"
$xml += '<autogroupmanagementoff>0</autogroupmanagementoff>';$xml += "`r`n"
$xml += '<instancename>'+$RSinstance+'</instancename>';$xml += "`r`n"
$xml += '<configsku>OnPremise</configsku>';$xml += "`r`n"
$xml += '<webstore enabled="false" configdb="false" />';$xml += "`r`n"
$xml += '<patch update="'+$patchUpdate+'" />';$xml += "`r`n"
$xml += '<muoptin optin="'+$MUoptin+'" />';$xml += "`r`n"
$xml += '<MonitoringServiceAccount type="DomainUser">';$xml += "`r`n"
$xml += '  <ServiceAccountLogin>'+$svcCRMMonitor+'</ServiceAccountLogin>';$xml += "`r`n"
$xml += '  <ServiceAccountPassword>'+$svcCRMMonitorPassword+'</ServiceAccountPassword>';$xml += "`r`n"
$xml += '</MonitoringServiceAccount>';$xml += "`r`n"
$xml += '</srsdataconnector>';$xml += "`r`n"
$xml += '</crmsetup>';$xml += "`r`n"
$xml | Out-File $SRSxmlfile

Write-Host " Installing SrsDataConnector...`n"
Start-Process $SRSInstallFile -ArgumentList "/Q /Config $SRSxmlfile" -Wait

#region EmailRouter
# https://support.microsoft.com/en-us/kb/951401
Write-Host "Downloading Microsoft Exchange Server MAPI Client and Collaboration Data Objects 1.2.1"
$source = 'http://bumboks.dk/ExchangeMapiCdo.MSI'
$destination = "$PSScriptRoot\ExchangeMapiCdo.msi"
Invoke-WebRequest $source -OutFile $destination
Write-Host " Installing ExchangeMapiCdo.msi`n"
Start-Process $destination -ArgumentList '/passive' -Wait

$xml = $null
$EmailRouterSetupXMLfile = "$PSScriptRoot\EmailRouterSetupConfig.xml"

Write-Host 'Creating Email Router XML answer file...'

$xml += '<CRMSetup>';$xml += "`r`n"
$xml += '<EmailRouter>';$xml += "`r`n"
$xml += '<Features>';$xml += "`r`n"
$xml += '  <SinkService />';$xml += "`r`n"
$xml += '  <RulesWizard />';$xml += "`r`n"
$xml += '</Features>';$xml += "`r`n"
$xml += '<Patch update="'+$patchUpdate+'"></Patch>';$xml += "`r`n"
$xml += '<muoptin optin="'+$MUoptin+'" />';$xml += "`r`n"
$xml += '<InstallDir>C:\Program Files\Microsoft Dynamics CRM Email Router</InstallDir>';$xml += "`r`n"
$xml += '</EmailRouter>';$xml += "`r`n"
$xml += '</CRMSetup>';$xml += "`r`n"
$xml | Out-File $EmailRouterSetupXMLfile

Write-Host " Installing Email Router...`n"
Start-Process $EmailRouterInstallFile -ArgumentList "/Q /CONFIG $EmailRouterSetupXMLfile" -Wait

if($nonHTTPS -eq $true) {New-Item -Path HKLM:\Software\Microsoft\MSCRM\DisableSecureDecryptionKey -Value "1" | Out-Null}
else {New-Item -Path HKLM:\Software\Microsoft\MSCRM\DisableSecureDecryptionKey -Value "0" | Out-Null}

# Make the Windows Service ”Microsoft CRM Email Router” run under the svcCRMEmailRouter account.
$service="displayname='Microsoft CRM Email Router'"

$svc=gwmi win32_service -filter $service
$svc.StopService() | Out-Null
$svc.change($null,$null,$null,$null,$null,$null,$account,$svcCRMEmailRouterpassword,$null,$null,$null) | Out-Null
$svc.StartService() | Out-Null

#region updates
function DownloadUpdate ($type,$url) {
    $file = $url.Split('/')[-1]
    $dest = "$CRMupdateDir\$file"
    Write-Host "Downloading $file"
    $uri = New-Object "System.Uri" "$url"
    $request = [System.Net.HttpWebRequest]::Create($uri)
    $response = $request.GetResponse()
    $totalLength = [System.Math]::Floor($response.get_ContentLength()/1024)
    $length = $response.get_ContentLength()
    $responseStream = $response.GetResponseStream()
    $destStream = New-Object -TypeName System.IO.FileStream -ArgumentList $dest, Create
    $buffer = New-Object byte[] 10KB
    $count = $responseStream.Read($buffer,0,$buffer.length)
    $downloadedBytes = $count
    while ($count -gt 0)
        [System.Console]::Write(" Downloaded {0}K of {1}K ({2}%)", [System.Math]::Floor($downloadedBytes/1024), $totalLength, [System.Math]::Round(($downloadedBytes / $length) * 100,0))
        $destStream.Write($buffer, 0, $count)
        $downloadedBytes += $count
    Write-Host ''
    New-Item "$CRMupdateDir\$type" -ItemType Directory | Out-Null
    Write-Host " Extracting... " -NoNewline
    Start-Process $CRMupdateDir\$file -ArgumentList "/extract:$CRMupdateDir\$type /passive" -Wait
    Write-Host "Installing... " -NoNewline
    if (Test-Path "$CRMupdateDir\$type\CrmUpdateWrapper.exe"){Start-Process "$CRMupdateDir\$type\CrmUpdateWrapper.exe" -ArgumentList "/quiet /norestart" -Verb RunAs -Wait}
    else{Start-Process msiexec.exe -ArgumentList "/i $CRMupdateDir\$type\MUISetup_1030_amd64.msi /quiet /norestart" -Verb RunAs -Wait}
    Write-Host "Done.`n"

if (!(Test-Path $CRMupdateDir)) {New-Item $CRMupdateDir -ItemType Directory | Out-Null}
DownloadUpdate Server $Server
DownloadUpdate Router $Router
DownloadUpdate SRS $SRS
DownloadUpdate MUI-ENU $MUIENU
DownloadUpdate MUI-DAN $MUIDAN

#region MaintenancePlan 
# https://habaneroconsulting.com/insights/create-developer-sql-maintenance-plans-using-sql-agent-jobs-and-powershell
Invoke-Command -ComputerName $SQLserver -ScriptBlock {
    $JobName = ("{0}_SQL_Maintenance" -f $env:COMPUTERNAME)
    $DropExisting = $false
    $InstanceName = "MSSQLSERVER"
    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | Out-Null
    # Get the Default Instance
    $srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server
    # Get the SQL Agent Service for the Instance
    $Service = Get-Service -DisplayName ("SQL Server Agent ({0})" -f $InstanceName)
    # Set the SQL Agent Service startup type to Automatic and attempt to start it
    if($Service -eq $null){
        Throw ("Sql Sserver Agent ({0}) Not Found" -f $InstanceName)
    } else {
    Write-Host "Setting SQL Agent Startup type to Automatic"
        $Service | Set-Service -StartupType Automatic -ErrorAction Stop
        if($Service.Status -ieq "Stopped"){
            Write-Host "Agent Not Running"
            Write-Host "Waiting for Service to Start." -NoNewline
            While($Service.Status -ieq "StartPending"){
                Write-Host "." -NoNewline
                Start-Sleep 2
            if($Service.Status -ine "Running"){
                Write-Host ""
                Throw "An error occurred while starting `"SQL SERVER AGENT ($InstanceName)`". Try starting the service Manually. Then re-run this command."
            Write-Host ".Started"
            Write-Host "Sleep for 10 Seconds While Agent wakes up..."
            Start-Sleep 10
            # Depending on the speed of your server, it may take longer than 10 seconds for the agent to wake up. You will know if the rest of the script fails.
    # Look for Existing Jobs with the same name.
        $Jobs = $srv.JobServer.Jobs
        foreach($Job in $Jobs){
            if($Job.Name -ieq $JobName){
                Write-Host ("This Server already has a Job Called `'{0}`'." -f $JobName)
                    Write-Host ("Dropping Job: `'{0}`'." -f $JobName)
                } else {
    } Catch {
        Throw $_
    # Define a Job object variable by supplying the Agent and the name arguments in the constructor and setting properties.
    $job = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Agent.Job -argumentlist $srv.JobServer, $JobName
    # Create the job on the instance of SQL Server Agent.
    Write-Host ("Creating job `'{0}`'." -f $JobName)
    $job.ApplyToTargetServer("(local)") #Job will run against the Agent's Local Server
    # Define a JobStep object variable by supplying the parent job and name arguments in the constructor.
    $jobstep = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Agent.JobStep -argumentlist $job, "Clean Up"

    $jobstep.Command = "SET QUOTED_IDENTIFIER ON 

    IF EXISTS (SELECT name from sys.indexes
                      WHERE name = N'CRM_AsyncOperation_CleanupCompleted')
          DROP Index AsyncOperationBase.CRM_AsyncOperation_CleanupCompleted
    CREATE NONCLUSTERED INDEX CRM_AsyncOperation_CleanupCompleted
    ON [dbo].[AsyncOperationBase] ([StatusCode],[StateCode],[OperationType])

    declare @DeleteRowCount int
    Select @DeleteRowCount = 2000
    declare @DeletedAsyncRowsTable table (AsyncOperationId uniqueidentifier not null primary key)
    declare @continue int, @rowCount int
    select @continue = 1
    while (@continue = 1)
    begin tran      
    insert into @DeletedAsyncRowsTable(AsyncOperationId)
          Select top (@DeleteRowCount) AsyncOperationId from AsyncOperationBase
          where OperationType in (1, 9, 12, 25, 27, 10) AND StateCode = 3 AND StatusCode in (30, 32)     
           Select @rowCount = 0
          Select @rowCount = count(*) from @DeletedAsyncRowsTable
          select @continue = case when @rowCount <= 0 then 0 else 1 end      
            if (@continue = 1)        begin
                delete WorkflowLogBase from WorkflowLogBase W, @DeletedAsyncRowsTable d
                where W.AsyncOperationId = d.AsyncOperationId             
     delete BulkDeleteFailureBase From BulkDeleteFailureBase B, @DeletedAsyncRowsTable d
                where B.AsyncOperationId = d.AsyncOperationId
     delete WorkflowWaitSubscriptionBase from WorkflowWaitSubscriptionBase WS, @DeletedAsyncRowsTable d
     where WS.AsyncOperationId = d.AsyncOperationID 
                delete AsyncOperationBase From AsyncOperationBase A, @DeletedAsyncRowsTable d
                where A.AsyncOperationId = d.AsyncOperationId             
                delete @DeletedAsyncRowsTable      
    --Drop the Index on AsyncOperationBase
    DROP INDEX AsyncOperationBase.CRM_AsyncOperation_CleanupCompleted"
    $jobstep.OnSuccessAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::GoToNextStep
    $jobstep.OnFailAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::QuitWithFailure
    # Create the job step on the instance of SQL Agent.

    $jobstep = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Agent.JobStep -argumentlist $job, "Update Statistics"

    $jobstep.Command = "UPDATE STATISTICS [dbo].[AsyncOperationBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[DuplicateRecordBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[BulkDeleteOperationBase] WITH FULLSCAN
    UPDATE STATISTICS [dbo].[WorkflowWaitSubscriptionBase] WITH FULLSCAN"

    $jobstep.OnSuccessAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::QuitWithSuccess
    $jobstep.OnFailAction = [Microsoft.SqlServer.Management.SMO.Agent.StepCompletionAction]::QuitWithFailure
    # Create the job step on the instance of SQL Agent.
    # Define a JobSchedule object variable by supplying the parent job and name arguments in the constructor.
    $jobsch =  New-Object -TypeName Microsoft.SqlServer.Management.SMO.Agent.JobSchedule -argumentlist $job, "Monthly_Job_Schedule"
    # Set properties to define the schedule frequency, and duration.
    $jobsch.FrequencyTypes = [Microsoft.SqlServer.Management.SMO.Agent.FrequencyTypes]::MonthlyRelative
    $jobsch.FrequencyRelativeIntervals = [Microsoft.SqlServer.Management.SMO.Agent.FrequencyRelativeIntervals]::Last
    $jobsch.FrequencyInterval = [Microsoft.SqlServer.Management.SMO.Agent.MonthlyRelativeWeekDays]::EveryDay
    $jobsch.FrequencyRecurrenceFactor = 1
    $jobsch.ActiveStartDate = Get-Date
    $starttime = New-Object -TypeName TimeSpan -ArgumentList 23, 30, 0
    $jobsch.ActiveStartTimeOfDay = $starttime
    # Create the job schedule on the instance of SQL Agent.
    Write-Host ("Job `'{0}`' successfully created..." -f $JobName)


#region removeAutoLogon
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultUserName
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name DefaultPassword
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name ForceAutoLogon

#region TheEnd
Write-Host ''
Write-Host '      .                             ..              .x+=:.         ..                                              ..  ' -ForegroundColor Green
Write-Host '  .x88888x.                   . uW8"       .8u     z`    ^%      dF                                               888B.' -ForegroundColor Green
Write-Host ' :8**888888X.  :>        u.   `t888       m888R-      .   <k    `88bu.             u.      u.    u.              48888E' -ForegroundColor Green
Write-Host ' f    `888888x./   ...ue888b   8888   .    98P      .@8Ned8"    `*88888bu    ...ue888b   x@88k u@88c.      .u    `8888Β΄' -ForegroundColor Green
Write-Host '`       `*88888~   888R Y888r  9888.z88N   ^8     .@^%8888"       ^"*8888N   888R Y888r ^"8888""8888"   ud8888.   Y88F ' -ForegroundColor Green
Write-Host ' \.    .  `?)X.    888R I888>  9888  888E  J"    x88:  `)8b.     beWE "888L  888R I888>   8888  888R  :888`8888.  `88  ' -ForegroundColor Green
Write-Host '  `~=-^   X88> ~   888R I888>  9888  888E +"     8888N=*8888     888E  888E  888R I888>   8888  888R  d888 `88%"   8F  ' -ForegroundColor Green
Write-Host '         X8888  ~  888R I888>  9888  888E         %8"    R88     888E  888E  888R I888>   8888  888R  8888.+"      4   ' -ForegroundColor Green
Write-Host '         488888   u8888cJ888   9888  888E          @8Wou 9%      888E  888F u8888cJ888    8888  888R  8888L        .   ' -ForegroundColor Green
Write-Host ' .xx.     88888X   "*888*P"   .8888  888"        .888888P`      .888N..888   "*888*P"    "*88*" 8888" `8888c. .+  u8N. ' -ForegroundColor Green
Write-Host '`*8888.   `88888>    `Y"       `%888*%"          `   ^"F         `"888*""      `Y"         ""   `Y"    "88888%   "*88% ' -ForegroundColor Green
Write-Host '  88888    `8888>                 "`                                ""                                   "YP`      ""  ' -ForegroundColor Green
Write-Host '  `8888>    `888                                                                                                       ' -ForegroundColor Green
Write-Host '   "8888     8%                                                                                                        ' -ForegroundColor Green
Write-Host '    `"888x:-"                                                                                                          ' -ForegroundColor Green
Write-Host '                                      Now go configure the CRM Email Router πŸ™‚                                         ' -ForegroundColor Cyan