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.
Video
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.
Clear-Host 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>' #Media $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. #Accounts $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>' #ReportingServices $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 #CRM XML # 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 = '10.0.0.1-255.0.0.0' # IP address and subnet mask, such as 157.56.137.105-255.255.255.0. 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. #Updates $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' #endregion ############################################################################## # 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) $ps.BeginInvoke() } if (!(Test-Path placeholder.tmp)) { Add-Clock | Out-Null Clear-Host 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 #endregion #region CreateUsers [ScriptBlock]$ScriptBlock = { param( [string]$CRMgroupOU, [string]$CRMSetupUser, [string]$CRMSetupUserPassword, [string]$svcCRMApp, [string]$svcCRMAppPassword, [string]$svcCRMDeploy, [string]$svcCRMDeployPassword, [string]$svcCRMSandbox, [string]$svcCRMSandboxPassword, [string]$svcCRMVSS, [string]$svcCRMVSSPassword, [string]$svcCRMAsync, [string]$svcCRMAsyncPassword, [string]$svcCRMMonitor, [string]$svcCRMMonitorPassword, [string]$svcCRMEmailRouter, [string]$svcCRMEmailRouterPassword, [string]$RSappPoolAccount, [string]$RSappPoolAccountPassword ) 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 #endregion #region LogonAsService # http://anexinetisg.blogspot.dk/2014/02/grant-users-log-on-as-service-right-via.html function Grant-LogOnAsService{ param( [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" } } if($sidstring){ $newSids = $sids + $sidstring Write-Host "`nNew Sids: " -NoNewline $newsids.Split(',') $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 } else{ 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 #endregion #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 { [cmdletBinding()] Param( [Parameter(Mandatory=$True)] [string]$computer, [Parameter(Mandatory=$True)] [string]$group, [Parameter(Mandatory=$True)] [string]$domain, [Parameter(Mandatory=$True)] [string]$user ) $de = [ADSI]"WinNT://$computer/$Group,group" $de.psbase.Invoke("Add",([ADSI]"WinNT://$domain/$user").path) } 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 #endregion # 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 = { param([string]$CRMSetupUser) Import-Module -Name SQLPS -DisableNameChecking Add-Type -AssemblyName "Microsoft.SqlServer.Smo, Version=10.0.0.0, 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 $sqlUser.Create() $smo.Logins["$env:USERDOMAIN\$CRMSetupUser"].AddToRole('sysadmin') } 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") $s.Connect() $sc = New-Object Management.ManagementClass("\\localhost\root\Microsoft\SqlServer\ReportServer\RS_$RSinstance\v12\admin:MSReportServer_ConfigurationSetting") $sc.Get() $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 = { param($script,$DBinstance) $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 = { param($script,$DBinstance) $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 #endregion #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 #endregion #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" #endregion Write-Host "`nRebooting..." Restart-Computer } else{ Add-Clock | Out-Null #region CRMinstall Clear-Host 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 #endregion #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 #endregion #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. $account="$env:USERDOMAIN\$svcCRMEmailRouter" $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 #endregion #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) $request.set_Timeout(5000) $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]::CursorLeft=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) $count=$responseStream.Read($buffer,0,$buffer.length) $downloadedBytes += $count } Write-Host '' $destStream.Flush() $destStream.Close() $destStream.Dispose() $responseStream.Dispose() 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 DownloadUpdate MUI-DAN-UPD $MUIDANUPD #endregion #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" $Service.Start() Write-Host "Waiting for Service to Start." -NoNewline $Service.Refresh(); While($Service.Status -ieq "StartPending"){ $Service.Refresh() 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" $srv.JobServer.Refresh() 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. Try{ $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) if($DropExisting){ Write-Host ("Dropping Job: `'{0}`'." -f $JobName) $Job.Drop() break } else { return } } } } 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.Create() $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 GO CREATE NONCLUSTERED INDEX CRM_AsyncOperation_CleanupCompleted ON [dbo].[AsyncOperationBase] ([StatusCode],[StateCode],[OperationType]) GO 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 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 end commit end --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.Create() $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].[WorkflowLogBase] 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. $jobstep.Create() # 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. $jobsch.Create(); Write-Host ("Job `'{0}`' successfully created..." -f $JobName) } #endregion #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 #endregion #region TheEnd #Clear-Host 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 Read-Host #endregion }