Using SQL LocalDB in a Windows Service - sql

I have a very small test application in which I'm trying to install a Windows Service and create a LocalDB database during the install process, then connect to that LocalDB database when the Windows Service runs.
I am running into huge problems connecting to a LocalDB instance from my Windows Service.
My installation process is exactly like this:
Execute an installer .msi file which runs the msiexec process as the NT AUTHORITY\SYSTEM account.
Run a custom action to execute SqlLocalDB.exe with the following commands:
sqllocaldb.exe create MYINSTANCE
sqllocaldb.exe share MYINSTANCE MYINSTANCESHARE
sqllocaldb.exe start MYINSTANCE
Run a custom C# action using ADO.NET (System.Data.SqlConnection) to perform the following actions:
Connect to the following connection string, Data Source=(localdb)\MYINSTANCE; Integrated Security=true
CREATE DATABASE TestDB
USE TestDB
CREATE TABLE ...
Start the Windows Service before the installer finishes.
The Windows Service is installed to the LocalSystem account and so also runs as the NT AUTHORITY\SYSTEM user account.
The service attempts to connect using the same connection string used above.
I am consistently getting the following error when trying to open the connection to the above connection string from within the Windows Service:
System.Data.SqlClient.SqlException (0x80131904): A network-related or
instance-specific error occurred while establishing a connection to
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. (provider: SQL Network Interfaces, error: 50
- Local Database Runtime error occurred. The specified LocalDB instance does not exist.
This is frustrating because both the msi installer custom action and the Windows Service are running under the same Windows user account (I checked, they're both NT AUTHORITY\System). So why the first works and the second does not is beyond me.
I have tried changing the connection strings used in the custom action and the Windows Service to use the share name (localdb)\.\MYINSTANCESHARE and I get the exact same error from the Windows Service.
I have tried changing the user account that the Windows Service logs on as to my Windows user account, which does work as long as I first run a command to add it to the SQL server logins for that instance.
I've also tried running a console application and connecting to the share name connection string and that works as well.
I've also tried connecting to the share name from SQL Server Management Studio and that works as well.
However none of these methods really solve my problem. I need a Windows Service because it starts up as soon as the computer starts up (even if no user logs on) and starts up no matter which user account is logged in.
How does a Windows Service connect to a LocalDB private instance?
I am using SQL Server 2014 Express LocalDB.

Picking up from the comments on the question, here are some areas to look at. Some of these have already been answered in those comments, but I am documenting here for others in case the info might be helpful.
Check here for a great source of info on SQL Server Express LocalDB:
SQL Server 2014 Express LocalDB
SqlClient Support for LocalDB
SqlLocalDB Utlity
Introducing LocalDB, an improved SQL Express (also look at the Q&A section at the end of the main post, just before the comments, as someone asked if LocalDB can be launched from a service, and the answer is:
LocalDB can be launched from a service, as long as the profile is loaded for the service account.
What version of .Net is being used? Here it is 4.5.1 (good) but earlier versions could not handle the preferred connection string (i.e. #"(localdb)\InstanceName"). The following quote is taken from the link noted above:
If your application uses a version of .NET before 4.0.2 you must connect directly to the named pipe of the LocalDB.
And according to the MSDN page for SqlConnection.ConnectionString:
Beginning in .NET Framework 4.5, you can also connect to a LocalDB database as follows:
server=(localdb)\\myInstance
Paths:
Instances: C:\Users{Windows Login}\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances
Databases:
Created via SSMS or direct connection: C:\Users{Windows Login}\Documents or C:\Users{Windows Login}
Created via Visual Studio: C:\Users{Windows Login}\AppData\Local\Microsoft\VisualStudio\SSDT
Initial Problem
Symptoms:
Database files (.mdf and .ldf) created in the expected location:
C:\Windows\System32\config\systemprofile
Instance files created in an unexpected location:
C:\Users\{current user}\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances
Cause (note taken from "SqlLocalDB Utility" MSDN page that is linked above; emphasis mine):
Operations other than start can only be performed on an instance belonging to currently logged in user.
Things to try:
Connection string that specifies the database (though maybe a long-shot if the error is regarding not being able to connect to the instance):
"Server=(LocalDB)\MYINSTANCE; Integrated Security=true ;AttachDbFileName=C:\Windows\System32\config\systemprofile\TestDB.mdf"
"Server=(LocalDB)\.\MYINSTANCESHARE; Integrated Security=true ;AttachDbFileName=C:\Windows\System32\config\systemprofile\TestDB.mdf"
Is the service running? Run the following from a Command Prompt:
TASKLIST /FI "IMAGENAME eq sqlservr.exe"
It should probably be listed under "Console" for the "Session Name" column
Run the following from a Command Prompt:
sqllocaldb.exe info MYINSTANCE
And verify that the value for "Owner" is correct. Is the value for "Shared name" what it should be? If not, the documentation states:
Only an administrator on the computer can create a shared instance of LocalDB
As part of the setup, add the NT AUTHORITY\System account as a Login to the system, which is required if this account is not showing as the "Owner" of the instance:
CREATE LOGIN [NT AUTHORITY\System] FROM WINDOWS;
ALTER SERVER ROLE [sysadmin] ADD MEMBER [NT AUTHORITY\System];
Check the following file for clues / details:
C:\Users{Windows Login}\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances\MYINSTANCE\error.log
In the end you might need to create an actual account to create and own the Instance and Database, as well as run your service. LocalDB really is meant to be user-mode, and is there any downside to having your service have its own login? And you probably wouldn't need to share the instance at that point.
And in fact, as noted by Microsoft on the SQL Server YYYY Express LocalDB MSDN page:
An instance of LocalDB owned by the built-in accounts such as NT AUTHORITY\SYSTEM can have manageability issues due to windows file system redirection; Instead use a normal windows account as the owner.
UPDATE (2015-08-21)
Based on feedback from the O.P. that using a regular User account can be problematic in certain environments, AND keeping in mind the original issue of the LocalDB instance being created in the %LOCALAPPDATA% folder for the user running the installer (and not the %LOCALAPPDATA% folder for NT AUTHORITY\System ), I found a solution that seems to keep with the intent of easy installation (no user to create) and should not require needing extra code to load the SYSTEM profile.
Try using one of the two built-in accounts that is not the LocalSystem account (which does not maintain its own registry info. Use either:
NT AUTHORITY\LocalService
NT AUTHORITY\NetworkService
Both have their profile folders in: C:\Windows\ServiceProfiles
While I have not been able to test via an installer, I did test a service logging on as NT AUTHORITY\NetworkService by setting my SQL Server Express 2014 instance to log on as this account, and restarted the SQL Server service. I then ran the following:
EXEC xp_cmdshell 'sqllocaldb c MyTestInstance -s';
and it created the instance in: C:\Windows\ServiceProfiles\NetworkService\AppData\Local\Microsoft\Microsoft SQL Server Local DB\Instances
I then ran the following:
EXEC xp_cmdshell N'SQLCMD -S (localdb)\MyTestInstance -E -Q "CREATE DATABASE [MyTestDB];"';
and it had created the database in: C:\Windows\ServiceProfiles\NetworkService

I was able to solve similar issue in our WiX installer recently. We have a Windows service, running under SYSTEM account, and an installer, where LocalDB-based storage is one of the options for database configuration. For some time (a couple of years actually) product upgrades and service worked quite fine, with no issues related to LocalDB. We are using default v11.0 instance, which is created in SYSTEM profile in C:\Windows\System32\config tree, and a database specified via AttachDbFileName, created in ALLUSERSPROFILE tree. DB provider is configured to use Windows authentication. We also have a custom action in installer, scheduled as deferred/non-impersonate, which runs DB schema updates.
All this worked fine until recently. After another bunch of DB updates, our new release started to fail after having upgraded over the former - service was unable to start, reporting infamous "A network-related or instance-specific error occurred while establishing a connection to SQL Server" (error 50) fault.
When investigating this issue, it became apparent that the problem is in a way WiX runs custom actions. Although non-impersonated CA-s run under SYSTEM account, the registry profile and environment remain that of current user (I suspect WiX loads these voluntary when attaching to user's session). This leads to incorrect path being expanded from the LOCALAPPDATA variable - the service receives SYSTEM profile one, but the schema update CA works with the user's one.
So here are two possible solutions. The first one is simple, but too intrusive to user's system - with cmd.exe started via psexec, recreate broken instance under the SYSTEM account. This was not an option for us as the user may have other databases created in v11.0 instance, which is public. The second option assumed lots of refactoring, but wouldn't hurt anything. Here is what to do to run DB schema updates properly with LocalDB in WiX CA:
Configure your CA as deferred/non-impersonate (should run under SYSTEM account);
Fix environment to point to SYSTEM profile paths:
var systemRoot = Environment.GetEnvironmentVariable("SystemRoot");
Environment.SetEnvironmentVariable("USERPROFILE", String.Format(#"{0}\System32\config\systemprofile", systemRoot));
Environment.SetEnvironmentVariable("APPDATA", String.Format(#"{0}\System32\config\systemprofile\AppData\Roaming", systemRoot));
Environment.SetEnvironmentVariable("LOCALAPPDATA", String.Format(#"{0}\System32\config\systemprofile\AppData\Local", systemRoot));
Environment.SetEnvironmentVariable("HOMEPATH", String.Empty);
Environment.SetEnvironmentVariable("USERNAME", Environment.UserName);
Load SYSTEM account profile. I used LogonUser/LoadUserProfile native API methods, as following:
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool LogonUser(
string lpszUserName,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[StructLayout(LayoutKind.Sequential)]
struct PROFILEINFO
{
public int dwSize;
public int dwFlags;
[MarshalAs(UnmanagedType.LPWStr)]
public String lpUserName;
[MarshalAs(UnmanagedType.LPWStr)]
public String lpProfilePath;
[MarshalAs(UnmanagedType.LPWStr)]
public String lpDefaultPath;
[MarshalAs(UnmanagedType.LPWStr)]
public String lpServerName;
[MarshalAs(UnmanagedType.LPWStr)]
public String lpPolicyPath;
public IntPtr hProfile;
}
[DllImport("userenv.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool LoadUserProfile(IntPtr hToken, ref PROFILEINFO lpProfileInfo);
var hToken = IntPtr.Zero;
var hProfile = IntPtr.Zero;
bool result = LogonUser("SYSTEM", "NT AUTHORITY", String.Empty, 3 /* LOGON32_LOGON_SERVICE */, 0 /* LOGON32_PROVIDER_DEFAULT */, ref token);
if (result)
{
var profileInfo = new PROFILEINFO();
profileInfo.dwSize = Marshal.SizeOf(profileInfo);
profileInfo.lpUserName = #"NT AUTHORITY\SYSTEM";
if (LoadUserProfile(token, ref profileInfo))
hProfile = profileInfo.hProfile;
}
Wrap this in an IDisposable class, and use with a using statement to build a context.
The most important - refactor your code to perform necessary DB updates in a child process. This could be a simple exe-wrapper over your installer DLL, or stand-alone utility, if your already have one.
P.S. All these difficulties could be avoided, if only Microsoft let uses choose where to create LocalDB instances, via command line option. Like Postgres' initdb/pg_ctl utilities have, for example.

I suggest using a different user account, and not using the System account, by doing the following:-
create a new account on the machine, and set that to be the account
under which the Windows Service runs. It's not good practice to use
the system account just to run an application, anyway, as the
permissions are excessive.
ensure that the permissions on the LocalDB files are set to allow the said user account to access the database (and thus continue to
use Integrated Security)
make sure it works by trying to connect to the DB (once installed) under the same user account by running sqlcmd or Management Studio
under the context of the said user, then connecting with Integrated
Security to ensure it works.
Some other things to try/consider:
have you checked the Windows Event log for any events that might be useful for diagnostic purposes?
Make sure that if you have any other versions of SQL Server (especially prior to 2012) that for the command-line tools, the %PATH% isn't set to find an older tools version first. Older tools don't support LocalDB.
It is possible also (as an alternative) to set up LocalDB to be shared with other users. This involves sharing the instance, and then granting access to other users. See the "Sharing Issues" section in this article: Troubleshoot SQL Server 2012 Express LocalDB.
There's also another SO article that may contain some more useful information there in the links within (change the language in the URL from Polish to English by changing pl-pl to en-us). His work-around is using SQL Server accounts, which might not be OK in your case.
This might also be useful, as it relates to security permissions being denied, and possible resolutions: https://dba.stackexchange.com/questions/30383/cannot-start-sqllocaldb-instance-with-my-windows-account

Trevor, the problem you have is with the MSI custom actions. You must configure them with "Impersonate=false" otherwise the custom actions will be executed under the current user context.
BTW what tool are you using to create the installer?
Depending on the tool you use, could you please provide screenshots or code snippets of your custom actions configuration?
The accepted answer from this post will give you some additional information about the different custom action execution alternatives:
Run ExeCommand in customAction as Administrator mode in Wix Installer
You will find additional information about impersonation here:
http://blogs.msdn.com/b/rflaming/archive/2006/09/23/768248.aspx

I wouldn't create the database under the system's localdb instance. I'd create it under the current user installing the product. This will make life much easier if you need to delete or manage the database. They can do this through sql management studio. Otherwise, you'll have to use psexc or something else to launch a process under the SYSTEM account to manage it.
Once the db is created, then use the share option you mentioned. The SYSTEM account can then access the database through the share name.
sqllocaldb share MSSqlLocalDb LOCAL_DB
When sharing, I've noticed you'll have to restart the the local db instance to actually access the db through the share name:
sqllocaldb stop MSSQLLocalDB
sqllocaldb start MSSQLLocalDB
Also, You may need to add the SYSTEM account as a db reader and writer to the database ...
EXEC sp_addrolemember db_datareader, 'NT AUTHORITY\SYSTEM'

Related

SSIS package failing - Working in BIDS but not working after deployment - Package contains excel connection with sql command [duplicate]

I have a OLEDB task that connects to ms-access database on local file system and dumps data into sql database.
Access db connection string is: Data Source=\\my-share\accessdbfile.accdb;Provider=Microsoft.ACE.OLEDB.16.0;
The SSIS package runs OK in visual studio. Access 2016 32-bit runtime is installed on this computer.
After deployment to SSIS catalog, right click and execute works OK. Access 2016 64-bit runtime is installed on this computer.
When this package is scheduled to run via SQL Agent job, using proxy/credential [domain user - example: domainname\user1] (having read permission on the access db file), then the job fails. The SSIS execution report shows error as: Unexpected Termination. There is no further information.
Suppose if I add the proxy credential (domainname\user1) to the local administrators group (in computer management) then the SQL Job runs OK. What could be the solution to this so I can give only the minimum required permissions?
The error is very difficult to debug as it doesn't occur when running via visual studio. Even when deployed to the SQL server and run from the SSIS catalog, the execution works OK. The error occurs only when the package is run via SQL server agent job (via credential/proxy) - the SSIS execution report doesn't show any helpful messages; and surprisingly the error gets resolved when the credential is added as local administrator on the computer - which is a bad practice.
The solution is analyse what kind of ms access file you are using and appropriately use the correct access runtime version (2013 vs 2016) and the correct provider value in the connection string.
Access runtime:
In my case, I uninstalled Access 2016 64-bit runtime and installed Access 2013 64-bit runtime.
Provider version:
I changed the provider version from 16.0 to 15.0, as shown below-
Before: Data Source=\\my-share\accessdbfile.accdb;Provider=Microsoft.ACE.OLEDB.16.0;
After: Data Source=\\my-share\accessdbfile.accdb;Provider=Microsoft.ACE.OLEDB.15.0;
Note:
There is no need to add the user to the local administrator group.
There is no need to login to the computer using that account.
Only read permission (under windows folder security) is sufficient assuming the SSIS packge will only read the ms access database.
It's hard to debug this only with the information provided, but in general:
The user running the job requires at least write and delete access on the underlying folder in which the Access database resides. This is required to generate a lockfile for the database.
If this is undesirable because the job may be modified by a malicious user, I've seen deployments where a copy is made in a temporary folder with write access and a size quota, and that temporary folder is removed as soon as the job finishes, regardless of if the job succeeded.

SQL LocalDb Automatic Instance Startup Failure when called from Visual Studio 2013, but not SQL Server Management Studio

Per MSDN Docs: http://msdn.microsoft.com/en-us/library/hh510202.aspx
LocalDB supports two kinds of instances: Automatic instances and Named instances.
I suspect this has something to do with my problem, so I am wondering if anyone knows how something like this gets automatically created. If I can quote from the docs, "One automatic instance of LocalDB exists for every version of LocalDB installed on the user’s computer."
Here is a copy of the relevant section in the above link:
Automatic instances of LocalDB are public. They are created and managed automatically for the user and can be used by any application.
One automatic instance of LocalDB exists for every version of LocalDB
installed on the user’s computer. Automatic instances of LocalDB
provide seamless instance management. There is no need to create the
instance; it just works. This allows for easy application installation
and migration to a different computer.
Different versions of LocalDB will have different instance naming conventions:
SQL 2012 LocalDB = V11.0
SQL 2014 LocalDB = ProjectsV12
I've seen others.
As long as the connecting app's connection string points to the correct instance, all is well:
(localdb)\V11.0
(localdb)\ProjectsV12
If I try to connect with SQL Server Management Studio to either instance (localdb)\V11.0 or (localdb)\ProjectsV12, I CAN, the "stopped" server "autostarts".
If I set the SQL Server instance in VS2013 to either instance (localdb)\V11.0 or (localdb)\ProjectsV12, I CANNOT, the "stopped" server "fails" to start. It attempts to start, but fails.
Here is the error message found in the instance error.log indicating why the instance start failed.
014-12-19 15:12:14.09 Logon Error: 17828, Severity: 20, State: 3.
2014-12-19 15:12:14.09 Logon The prelogin packet used to open the connection is structurally invalid; the connection has been closed. Please contact the vendor of the client library. [CLIENT: <named pipe>]
I may have found a clue here:
On one of my machines where Automatic Instancing works, the sqllocaldb command outputs following:
C:\>sqllocaldb info v11.0
Name: v11.0
Version: 11.0.3000.0
Shared name:
Owner: AM\Z617699
Auto-create: Yes <-- Yes? - and I have no idea how this is set.
State: Stopped
Last start time: 12/18/2014 5:18:46 PM
Instance pipe name:
On one of my other machines where Automatic Instancing does NOT work, the sqllocaldb command outputs following:
C:\>sqllocaldb info v11.0
Name: v11.0
Version: 11.0.3000.0
Shared name:
Owner: AM\Z617699
Auto-create: No <-- No? - and I have no idea how this is set.
State: Stopped
Last start time: 12/18/2014 5:18:46 PM
Instance pipe name:
I have spent days trying to find the answer to this question. Here is a link to an MSDN forum post that outlines all the unsuccessful steps I have taken to resolve this issue:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/83ad45d5-15c3-4463-bc0c-6c4899bf947e/localdb-visual-studio-2013-will-not-automatically-start-the-sql-2014-localdb-projectsv12-instance?forum=sqlexpress
The workaround is to just start the instance manually before you start VS2013. I'm just trying to resolve this issue so I can get an "Automatic Instance" image for all our developers.
I hope you just know he answer. :-)
Thanks, Dave
I had the same issue.
I resolved it by deleting and recreating the instance from command line:
Open the command line
Delete the session by typing: sqllocaldb delete "v11.0"
Recreate the instance with: sqllocaldb create "v11.0"
The new instance allows auto creation, and solves the issue.
The solution was taken from:
http://answers.flyppdevportal.com/categories/sqlserver/sqlexpress.aspx?ID=8bcb5f1e-0240-4df3-8a5e-7e3e73e1c45b
I had the same problem on VS2015 and SQL2016
the problem my dev station is a laptop, project explorer i think uses tcpip connection, while SQLeplorer local file or so.
It worked after i made sure that SQL used the Network card, and that it had a cable plugged in (so SQL could server the request over TCP using that IP) which it couldnt over wifi (by default?)
I had the same problem. One of the problem may be an older installed version of this product. Try to delete the database instances which are located in the following folder:
C:\Windows\System32\config\systemprofile\AppData\Local\Microsoft\Microsoft
SQL Server Local DB\Instances\VeeamEndPoint
After that it works for me!!!

Error accessing the database DSN

I have an issue with logging a Support user into an Application that has a SQL Server backend.
When configuring the application itself, the SQL set-up asked me to assign whether the Security to access the Application would be Windows Authentication or SQL: server Authentication, I chose Windows Authentication, and as I was using a login called
'LabUser1' I have been able to login to the application fine.
However, when I logon to the server using a different windows login, this time 'Support', SQL keeps giving me the error:
Error accessing the database DSN
Now I know the reason is because the install of SQL happened using the 'Labuser1' profile, but how can I create a script that will allow me to add the 'Support' user to the 'Allowed Logins' so that I can logon to the app server and at least open the Application? (I have seperate logins for when I see the applicatiojn login window, so please don't confuse the matter by thinking it is a simple case of creating a login for Support....I am talking about logging into the server)
The current batch file I am trying to run is:
sqlcmd -S localhost\OCDBB01 -i createSupportlogin.sql
Then I run this batch file after having created the following SQL script:
CREATE LOGIN OCDMW1\Support FROM WINDOWS
GO
Your description of the situation is a bit confusing to me however it appears that the "SQL setup" that is part of the application configuration created a ODBC DSN that uses the credentials of person logging into the machine as the login for SQL Server.
Simply creating a new (correct) login to the SQL instance may not resolve this issue since that does nothing to modify the DSN. If you are tied to using Window Authentication for SQL access it might be necessary to create multiple DSNs for the application to use and find a way to have the correct DSN associated to the right login for the application to use.

sql server 2012: cannot alter the login sa

I'm trying to create a database on my local machine using SSMS version 11.0.2100.60. I've run the application as administrator, logged in using Windows authentication, and I've added MYDOMAIN\my-username to the Logins. However if I try to create a db with this login I get the message
CREATE DATABASE permission denied in database 'master'.
(Microsoft SQL Server, Error: 262)
If I try to add the privelage dbcreator to my user, I get the following error.
User does not have permission to perform this action.
(Microsoft SQL Server, Error: 15247)
I can't log in as sa as I don't know/remember the password (is there a preset default?), and if I try to change the password I get the message:
Cannot alter the login 'sa', because it does not exist or you do not have permission.
(Microsoft SQL Server, Error: 15151)
Finally I note that the account 'sa' is disabled, and if I try to enable it I get the same error as before. Is there any way around this or do I need to re-install?
Version info:
Microsoft SQL Server Management Studio 11.0.2100.60
Microsoft Analysis Services Client Tools 11.0.2100.60
Microsoft Data Access Components (MDAC) 6.2.9200.16384
Microsoft MSXML 3.0 4.0 6.0
Microsoft Internet Explorer 9.10.9200.16635
Microsoft .NET Framework 4.0.30319.18051
Operating System 6.2.9200
I found the answer here:
In order to start SQL Server in single-user mode, you can add the
parameter “-m” at the command line. You can also use the SQL Server
Configuration Manager tool, which provides proper controls for the
file access and other privileges. To use the Configuration Manager
tool to recover your system, use the following steps:
Open the Configuration Manager tool from the "SQL Server 2005| Configuration" menu
Stop the SQL Server Instance you need to recover
Navigate to the “Advanced” tab, and in the Properties text box add “;–m” to the end of the list in the “Startup parameters” option
Click the “OK” button and restart the SQL Server Instance
A little more specific :
Open Sql Configuration Manager.
Select SQL Server Services.
On the right hand side, select the instance.
Right click on it and open properties.
In the advanced tab attach ";-m" at the end of the Startup Parameters field.
Apply and restart the service.
Now you have privilege to enable "sa" user and modify its password.
once done, remove ";-m" and restart the service.
You are good to go.
I'd like to point out an alternative answer laid out on DBA SE. Download PSExec onto the box that is having the problem and follow the instructions laid out in this blog post to effortlessly change admin settings using the NT Authority\System account.
./psexec -s -i "C:\...\Ssms.exe"
Wanted to share this solution as it solved my problem!

SQLExpress connection fails in IIS 7 w/ user instance error - "Failed to generate a user instance

Mainly looking to answer my question #1 below, but more knowledge would be appreciated.
I tried to use these resources during my investigation, but was unsuccessful:
http://social.msdn.microsoft.com/Forums/en/sqldatabaseengine/thread/f5eb164d-9774-4864-ae05-cac99740949b (For this error: Failed to generate a user instance of SQL Server due to failure in retrieving the user's local application data path. Please make sure the user has a local user profile on the computer. The connection will be closed.)
http://social.msdn.microsoft.com/forums/en-US/sqlexpress/thread/6dfdcc22-7a81-4e8f-a947-c1ce6982d4b3/ (For this error: CREATE DATABASE permission denied in database master. An attempt to attach an auto-named database for file ? failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.)
Questions
1.) Why does this error occur while running the Telerik Rad Controls for ASP.NET AJAX "Live Demos" project with IIS 7 (Running Telerik Live Demos works fine using ASP.NET Development Server with this connection string)
Failed to generate a user instance of SQL Server due to failure in retrieving the user's local application data path. Please make sure the user has a local user profile on the computer. The connection will be closed.
2.) How is creating a SQL Server Express instances different in IIS 7, from ASP.NET Development Server & SSMSE
3.) Are there certain attributes of a SQL connection string not allowed when running a website on different contexts (based on #2).
Environment:
I'm not running the "Live Demos" .NET 3.5 ASP.NET web application via the ASP.NET Development Server (feature that pops up in your system tray and picks a port for you after clicking play in Visual Studio). That works just fine! I'm running the website on IIS 7. SQL Server Express is using the NETWORK SERVICE user in Control Panel > Administrative Tools > Services > SQL Server (SQLExpress).
Using this connection string provided with the installed "Live Demos" web application demo project:
<add name="NorthwindConnectionString"
connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|Northwind.mdf;Integrated Security=True;User Instance=True"
providerName="System.Data.SqlClient" />
I've tried setting "User Instance=False", but that just throws another error:
CREATE DATABASE permission denied in database master. An attempt to attach an auto-named database for file ? failed. A database with the same name exists, or specified file cannot be opened, or it is located on UNC share.
(where "?" is the path of the *.mdf file - C:\Users\\MyDocuments\Visual Studio 2008\Projects\TelerikDemos\Telerik\RadControls for ASP.NET AJAX Q2 2011\Live Demos\App_Data\Northwind.mdf .. Stack Overflow italics is broken with some of those characters, so I had to remove that path)
Someone answered me on a previous question to set this "User Instance=False", but it appears User instances have nothing to do with whether or not you use SQL Express. User Instances are simply a feature of SQL Express that allows a very unprivileged user to host a database instance in it's own user context.
Note, this Northwind database is stored in an *.mdf file in the App_Data folder (under the "Live Demos" root application directory) along with the *.ldf (log file). I did previously try attaching the *.mdf files as actual databases under the "Databases" folder (in the SSMSE Object Explorer tree), but later removed them.
Web application "Live Demos" root folder (and nested folders/files) have the following users assigned with ALL privileges:
- IIS APPPOOL\Telerik ("Telerik" is the name of my application pool in IIS 7 for this site)
- IUSR
- NETWORK SERVICE
Making a note for myself about this SQLExpress master database query:
SELECT * FROM sys.dm_os_child_instances
Also tried different combinations of *.mdf & *.ldf permissions while also changing the user on the SQL Server (SQLExpress) Windows 7 service (Control Panel > Administrative Tools > Services) .. and also restarted the service after making those changes.
To reproduce:
download the Telerik Rad Controls for ASP.NET AJAX. Set the permimssions I mentioned in the "Live Demos" folder under Program Files\Telerik, change the .NET version of the web application to .NET 3.5, switch out their 3.5 web.config file with the normal web.config file in that folder. You have to use Visual Studio 2010, but I am running this in Visual Studio 2008 (with a little grunt work I did because our company is not yet on VS2010). Also switch out the proper Bin35 assemblies into the "Live Demos" folder Bin folder. Compile the solution. Create an IIS 7 website. Add Windows authentication. Enabled anonymous and Windows authentication.. all others are disabled. Set application pool to use Classic and 32 bit.
Then navigating to this URL and clicking the "First Look" image.
http://localhost/combobox/examples/overview/defaultcs.aspx
====================
More evidence will be provided if requested.
You are using a connection string with trusted authentication = true. This means that the connection uses the security context of the calling process.
When you run with the development server you are running in the security context of the logged in user, so every thing works fine.
When you run in IIS you are in the security context of the application pool process, which is NETWORK SERVICE, which does not have a user profile, therefore it crashes.
You can fix it by either:
Change the identity of the application pool to a normal user with access to the database
Use a connection string with user name and password
IIS doesn't load the Windows user profile, but certain applications might take advantage of it anyway to store temporary data. SQL Express is an example of an application that does this. However, a user profile has to be created to store temporary data in either the profile directory or in the registry hive. The user profile for the Network Service account was created by the system and was always available. However, with the switch to unique Application Pool identities, no user profile is created by the system. Only the standard application pools (DefaultAppPool and Classic .NET AppPool) have user profiles on disk. No user profile is created if the Administrator creates a new application pool.
However, if you want, you can configure IIS application pools to load the user profile by setting the LoadUserProfile attribute to "true".
https://learn.microsoft.com/en-us/iis/manage/configuring-security/application-pool-identities