[英]RSConfig generates a Dsn Connection String doesn't work
TL;DR . TL; DR 。
Repro steps, take a backup of your C:\\Program Files\\Microsoft SQL Server\\MSRS13.SSRS\\Reporting Services\\ReportServer\\RsReportServer.config
Repro步骤,备份您的C:\\Program Files\\Microsoft SQL Server\\MSRS13.SSRS\\Reporting Services\\ReportServer\\RsReportServer.config
Run this command to update the connection string in SSRS's config: 运行此命令以更新SSRS配置中的连接字符串:
C:\Program Files (x86)\Microsoft SQL Server\130\Tools\Binn>rsconfig -c -s <ServerName> -i <instanceNameIfNotDefault> -d "reportserver$ssrs" -a SQL -u sa -p "YourSAPassword" -t
Now browse to the SSRS website and it doesn't work! 现在浏览到SSRS网站,它不起作用! To fix it either restore your config file or run through the SSRS GUI tool and it works! 要修复它,请恢复配置文件或运行SSRS GUI工具,它可以正常工作!
How does the RsConfig utility work? RsConfig实用程序如何工作?
Background 背景
After I install SSRS on an Windows 2016 Server and restore the 2 databases I need to change the Connection String in SSRS configuration file to point to the new SQL server name/instance. 在Windows 2016 Server上安装SSRS并恢复2个数据库后,我需要更改SSRS配置文件中的连接字符串以指向新的SQL Server名称/实例。
Problem 问题
When I try to change the encrypted Connection String in C:\\Program Files\\Microsoft SQL Server\\MSRS13.SSRS\\Reporting Services\\ReportServer\\RsReportServer.config
file using the RSConfig utility: 当我尝试使用RSConfig实用程序更改C:\\Program Files\\Microsoft SQL Server\\MSRS13.SSRS\\Reporting Services\\ReportServer\\RsReportServer.config
文件中的加密连接字符串时:
C:\Program Files (x86)\Microsoft SQL Server\130\Tools\Binn>rsconfig -c -s Server0012 -i SSRS -d "reportserver$ssrs" -a SQL -u sa -p "P@ssw0rd!" -t
It changes the Dsn Connection String in the RsReportServer.config. 它更改RsReportServer.config中的Dsn连接字符串。
Before: <Dsn>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAE+tJc/4Vs0a0fdH0tCY8kgQAAAAiAAAAUgBlAHAAbwByAHQAaQBuAGcAIABTAGUAcgB2AGUAcgAAABBmAAAAAQAAIAAAAC2DBxZFsfVB16r0e3...... * 之前: <Dsn> AQAAANCMnd8BFdERjHoAwE / Cl + sBAAAAE + tJc / 4Vs0a0fdH0tCY8kgQAAAAiAAAAUgBlAHAAbwByAHQAaQBuAGcAIABTAGUAcgB2AGUAcgAAABBmAAAAAQAAAAAAC2DBxZFsfVB16r0e3 ...... *
After: <Dsn>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAE+tJc/4Vs0a0fdH0tCY8kgQAAAAiAAAAUgBlAHAAbwByAHQAaQBuAGcAIABTAGUAcgB2AGUAcgAAABBmAAAAAQAAIAAAAO2nOjFDJMo........ * 之后: <Dsn> AQAAANCMnd8BFdERjHoAwE / Cl + sBAAAAE + tJc / 4Vs0a0fdH0tCY8kgQAAAAiAAAAUgBlAHAAbwByAHQAaQBuAGcAIABTAGUAcgB2AGAAcgAAABBmAAAAAQAAAAAAAAnAnAnAnFnJMo ........ *
However after this change, browsing to the SSRS Website results in the error: 但是,在此更改后,浏览到SSRS网站会导致错误:
The report server can't connect to its database. 报表服务器无法连接到其数据库。 Make sure the database is running and accessible. 确保数据库正在运行且可访问。 You can also check the report server trace log for details. 您还可以检查报表服务器跟踪日志以获取详细信息。
If I run the SQL Reporting Services Configuration Tool (GUI) and change the Dsn Connection String browsing to the SSRS Website works! 如果我运行SQL Reporting Services配置工具(GUI)并更改Dsn连接字符串浏览到SSRS网站工作!
Obviously it changes the Dsn but I can't work out what else it does whilst the GUI tool is running. 显然它改变了Dsn,但我无法弄清楚它在GUI工具运行时做了什么。 I've used ProcessMonitor and I've seen that the GUI tool does NOT use RSConfig.exe utility, it uses itself RsConfigTool.exe! 我用的ProcessMonitor和我见过的GUI工具不使用RSConfig.exe工具,它使用自身RsConfigTool.exe! So I can't even capture command-line arguments of what the actual command/connection string should be. 所以我甚至无法捕获实际命令/连接字符串应该是什么的命令行参数。 Also each time we change the connection string a new random one is generated so not sure how to do comparison's of actual vs expected. 此外,每次我们更改连接字符串时,都会生成一个新的随机字符串,因此不确定如何进行实际与预期的比较。
I did a WinDiff of Registry keys and apart from some encrypted hexadecimal diffs, nothing stood out. 我做了一个WinDiff的注册表键,除了一些加密的十六进制差异,没有什么突出。
I run SQLProfiler and there were a bunch of grants that I have emulated in my PowerShell script, eg: 我运行SQLProfiler,我在PowerShell脚本中有一些赠款,例如:
$sqls += @"
USE [ReportServer`$SSRSTempDB]
if not exists (select * from sysusers where issqlrole = 1 and name = 'RSExecRole')
BEGIN
EXEC sp_addrole 'RSExecRole'
END;
GO
My hunch is the $ sign in the SQL Database Name and the @ in the "made up/simulated" password are not getting escaped when I run the commands, eg: 我的预感是SQL数据库名称中的$符号,当我运行命令时,“制作/模拟”密码中的@不会被转义,例如:
$MachineName = "server0012"
$instanceName = "SSRS"
$saPassword = "P@ssw0rd!"
$rsConfigPath = "C:\Program Files (x86)\Microsoft SQL Server\130\Tools\Binn\rsconfig.exe"
$setupArgs = -join('-c -s "', $MachineName,'" -i "', $instanceName,'" -d ','"ReportServer`$SSRS" -t -a SQL -u "sa" -p "', $saPassword,"""")
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process
Write-Host $rsConfigPath $setupArgs
$args = $setupArgs.Split(" ")
& "$rsConfigPath" $args
Restart-Service -Force "SQL Server ($instanceName)"
When I run these vanilla commands in Command Prompt (no need to escape PowerShell characters): 当我在命令提示符中运行这些vanilla命令时(无需转义PowerShell字符):
rsconfig -c -s Server0012 -i SSRS -d "reportserver$ssrs" -a SQL -u sa -p "P@ssw0rd!"
It changes the Dsn Connection String but browsing to SSRS Website gives same error (above). 它更改了Dsn连接字符串,但浏览到SSRS网站会出现同样的错误(上图)。
How can I find out what else RsConfigTool.exe does when changing the Current Report Server Database? 如何在更改当前报表服务器数据库时找出RsConfigTool.exe的其他内容? Or any guesses why the Connection String generated using the RSConfig Utility is out of whack - I've tried many different combinations, seems like only the RSConfigTool can actually do it? 或者任何猜测为什么使用RSConfig实用程序生成的连接字符串是不成功的 - 我尝试了很多不同的组合,似乎只有RSConfigTool才能真正做到这一点?
Note 1: 注1:
I'm scripting this all up as a DevOps project and we are baking these images with packer, so nothing can be done manually. 我正在编写这个作为DevOps项目的脚本,我们正在用打包器烘焙这些图像,因此无法手动完成任何操作。
Note 2: 笔记2:
The Machine is joined to the domain and renamed after SQL installed. 机器加入域并在安装SQL后重命名。 So using a Configuration.ini file I don't think will work. 所以使用Configuration.ini文件我认为不会起作用。
The trick is you need to use the Powershell Invoke-Expression
command, the server name has to include the instance name without quotes server\\instance, and you DO need to escape the $ sign in the RsConfig.exe command: -d ','"reportserver<tilda>$ssrs"'
诀窍是您需要使用Powershell Invoke-Expression
命令,服务器名称必须包含实例名称而不包含引号server \\ instance,并且您需要转义RsConfig.exe命令中的$符号: -d ','"reportserver<tilda>$ssrs"'
<tilda> = ` The tilda key that escapes the $ sign, see in script below. <tilda> = `逃脱$符号的tilda键,请参阅下面的脚本。
If you don't use Invoke-Expression
and escape the $ sign the DatabaseName is called ReportServer not ReportServer$SSRS 如果不使用Invoke-Expression
并转义$ sign,则DatabaseName称为ReportServer而不是ReportServer $ SSRS
You can see this in the SSRS Logs: 您可以在SSRS日志中看到:
library!WindowsService_1!30c!05/17/2019-03:56:29:: e ERROR: Throwing Microsoft.ReportingServices.Library.ReportServerDatabaseUnavailableException: , Microsoft.ReportingServices.Library.ReportServerDatabaseUnavailableException: The report server cannot open a connection to the report server database. 库!WindowsService_1!30c!05/17 / 2019-03:56:29 :: e错误:抛出Microsoft.ReportingServices.Library.ReportServerDatabaseUnavailableException:,Microsoft.ReportingServices.Library.ReportServerDatabaseUnavailableException:报表服务器无法打开与报表的连接服务器数据库 A connection to the database is required for all requests and processing. 所有请求和处理都需要与数据库的连接。 ---> System.Data.SqlClient.SqlException: A network-related or instance-specific error occurred while establishing a connection to SQL Server. ---> System.Data.SqlClient.SqlException:建立与SQL Server的连接时发生与网络相关或特定于实例的错误。 The server was not found or was not accessible. 服务器未找到或无法访问。 Verify that the instance name is correct and that SQL Server is configured to allow remote connections. 验证实例名称是否正确,以及SQL Server是否配置为允许远程连接。 (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server) (提供者:命名管道提供程序,错误:40 - 无法打开与SQL Server的连接)
Here is the script I use to fix a broken SQL install on a server that's been renamed: 这是我用于在已重命名的服务器上修复损坏的SQL安装的脚本:
Param(
[parameter(mandatory=$true,helpmessage="New Machine Name")]
[string]$MachineName,
[parameter(mandatory=$false,helpmessage="SQL Instance Name")]
[string]$instanceName = "SSRS",
[parameter(mandatory=$false,helpmessage="SQL SA Password")]
[string]$saPassword = "P@ssword1" #this is encrypted IRL
)
#1. Start the logging
Start-Transcript -Path "C:\temp\rename-ssrs-computer.txt"
#2. Change the SQL Server's name
Write-Host "Change the SQL Server Instance Name to $MachineName"
$moduleName = "SqlServer"
Import-Module $moduleName -Verbose
$sql = 'select @@SERVERNAME'
$serverNameQry = Invoke-SqlCmd -Serverinstance ".\$instanceName" -Query $sql -username "sa" -password $saPassword -querytimeout ([int]::MaxValue)
$serverName = $serverNameQry.Column1
$sql = -join('sp_dropserver ''', $serverName,'''
GO
sp_addserver ''', $MachineName, "\", $instanceName,''',''local''
GO
')
Invoke-SqlCmd -Serverinstance ".\$instanceName" -Query $sql -username "sa" -password $saPassword -querytimeout ([int]::MaxValue)
#3. Change the SSRS database permissions
$sqls = @()
$sqls += @"
USE master
DECLARE @AccountName nvarchar(260)
SET @AccountName = SUSER_SNAME(0x010100000000000514000000)
if not exists (select name from syslogins where name = @AccountName and hasaccess = 1 and isntname = 1)
BEGIN
EXEC sp_grantlogin @AccountName
END;
GO
"@
#..... all the SQL Profile trace outputs...#
Foreach ($sql in $sqls)
{
Invoke-SqlCmd -Serverinstance ".\$instanceName" -Query $sql -username "sa" -password $saPassword -querytimeout ([int]::MaxValue)
}
#4. Change all the registry key values with the AMI Original Computer Name
Write-Host "Change the SQL Server Name in the Registry to $MachineName"
$txt = -join('Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\130\Machines]
"OriginalMachineName"="',$MachineName,'"
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\90\Machines]
"OriginalMachineName"="',$MachineName,'"
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\140\Machines]
"OriginalMachineName"="',$MachineName,'"
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\130\Machines]
"OriginalMachineName"="',$MachineName,'"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Services\SSIS Server]
"GroupPrefix"="SQLServerDTSUser$',$MachineName,'"
"LName"=""
"Name"="MsDtsServer"
"Type"=dword:00000004
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\Services\SSIS Server]
"GroupPrefix"="SQLServerDTSUser$',$MachineName,'"
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Services\Report Server]
"Name"="ReportServer"
"LName"="ReportServer$"
"Type"=dword:00000006
"GroupPrefix"="SQLServerReportServerUser$',$MachineName,'$"
[HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Microsoft SQL Server\Services\Report Server]
"Name"="ReportServer"
"LName"="ReportServer$"
"Type"=dword:00000006
"GroupPrefix"="SQLServerReportServerUser$',$MachineName,'$"'
)
Add-Content "C:\temp\output.reg" $txt
regedit /s "C:\temp\output.reg"
#5. Set the encrypted connection string DONT CHANGE THIS!!!
$rsConfigPath = "C:\Program Files (x86)\Microsoft SQL Server\130\Tools\Binn\"
$setupArgs = -join('-c -s ', $MachineName, '\' , $instanceName,' -i ', $instanceName,' -d ','"reportserver`$ssrs"', ' -t -a SQL -u sa -p "', $saPassword,'"')
Write-Host "Setup args for RSConfig $rsConfigPath $setupArgs"
Write-Host "Running RSConfig"
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process
Write-Host $rsConfigPath $setupArgs
Set-Location "$rsConfigPath"
Invoke-Expression $("rsconfig.exe " + $setupArgs)
Write-Host "RSConfig Dsn complete, new Connection string under Dsn saved to rsconfig.config file."
#6. Restart the SQL Service
Write-Host "Restarting $instanceName"
Restart-Service -Force "SQL Server ($instanceName)"
Write-Host "Restarted $instanceName"
#7. Set regional format (date/time etc.) to English (Australia) - this applies to all users
Import-Module International
Set-Culture en-AU
# Check language list for non-US input languages, exit if found
$currentlist = Get-WinUserLanguageList
$currentlist | ForEach-Object {if(($.LanguageTag -ne "en-AU") -and ($.LanguageTag -ne "en-US")){exit}}
# Set the language list for the user, forcing English (Australia) to be the only language
Set-WinUserLanguageList en-AU -Force
Set-TimeZone -Name "AUS Eastern Standard Time"
# Lastly Stop the transcript (before the PC gets rebooted by the calling script).
Stop-Transcript
The issue is not with the RsConfigTool.exe. 问题不在于RsConfigTool.exe。 It works, and indeed changes the connection string properly. 它工作正常,并确实正确地更改了连接字符串。
The issue simply boils down to single quotes vs. double quotes and having a $ sign in the name. 问题简单归结为单引号与双引号以及名称中的$符号。
When you enclose a string in double quotation marks (a double-quoted string), variable names that are preceded by a dollar sign ($) are replaced with the variable's value before the string is passed to the command for processing. 将字符串括在双引号(双引号字符串)中时,在将字符串传递给命令进行处理之前,将以美元符号($)开头的变量名替换为变量的值。
We can see this when we try to output the database name: 当我们尝试输出数据库名称时,我们可以看到这一点:
PS C:\> Write-Output "ReportServer$SSRS"
ReportServer
As we can see, it returns "ReportServer" and then the contents of the $SSRS
variable (which is empty). 我们可以看到,它返回“ReportServer”,然后返回$SSRS
变量的内容 (为空)。
To prove this, if we create and set a value to the $SSRS
variable: 为了证明这一点,如果我们为$SSRS
变量创建并设置一个值:
PS C:\> $SSRS = "SomethingElse"
PS C:\> Write-Output "ReportServer$SSRS"
ReportServerSomethingElse
We get "SomethingElse" ;-). 我们得到“SomethingElse”;-)。 But if we enclose it in single quotes, it does not do a variable replacement: 但是如果我们用单引号将它括起来,它就不会做变量替换:
PS C:\> Write-Output 'ReportServer$SSRS'
ReportServer$SSRS
So, the fix, is when calling the RsConfigTool.exe tool from PowerShell, simply replace the double quotes with single quotes: 因此,修复是在从PowerShell调用RsConfigTool.exe工具时,只需用单引号替换双引号:
rsconfig -c -s Server0012 -i SSRS -d 'reportserver$ssrs' -a SQL -u sa -p 'P@ssw0rd!' -t
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.