question

paws27284 avatar image
paws27284 asked

Receiving error msg when executing bat file with SQLCMD

I have created a bat file on a user's desktop that contains a call to sqlcmd, it accesses the sql server and initiates a sql job. I am using the same id and password as all of the SSIS packages use on this server. The users has Windows 7 and the SQL version is 2008 R2 Here is the call in the bat file: sqlcmd -S "servername" -U "loginid" -P "password" -i \\\servername\\d\\applications\\scripts\\appname\\KHMonthly.sql -o \\\servername\\d\\applicationlogs\\appname\\KH_Monthly_Call.log The SQL script contains: execute msdb.dbo.sp_start_job @job_name = 'Monthly Extract' Go The error is Error occurred while opening or operating on file \\\servername\\d\\applications\\scripts\\appname\\KHMonthly.sql I know the password and id are correct for the execution of the sql script, but does the user who is executing the bat file have to have permission to the sql server? I am trying to avoid that. Suggestions? Thanks! Maggie
sqlcmd
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Oleg avatar image
Oleg answered
@paws27284 Is it possible that the path is incorrect? What is **d**? If it is a drive name then should it be **d$** (admin share)? Please check that pasting the path (without the file name) into windows explorer window address bar actually opens the folder containing the file. If it does then please ask the user to do the same. It looks like the problem might be related to either the spelling of the file path or else to the lack of permissions for that user to the share where the file is located. <\!-- **Begin Edit** You can try using the C# code below, it should help to figure out the source of the problem. Generally speaking, when you use sqlcmd to execute the script from the file, and the script executes the procedure to start a job then the following must take place: The Active directory user (the one who is invoking the batch file from her computer) does not need any permissions to the SQL Server, but does need to have at least READ permission to read the contents of the .SQL file. If logging is desired then she also must have the permissions to write to the log file The user specified with user ID and password (SQL Authentication) must: - Exist as a valid login on the SQL Server instance - Exist as a user in msdb database (mapped to that login) - Have a role membership to SQLAgentUserRole and SQLAgentOperatorRole msdb database roles. For example, suppose that the login info specified in the sqlcmd file is valid, which means that it already exists as a valid login to that SQL Server instance. Running the script below will create a user in msdb database and add the user to the database roles, which is necessary to have enough permissions to execute the procedure to start the job. use msdb; go -- create user in msdb database create user [some_user] for login [some_user]; go use msdb; go -- make the user a member of 2 database roles: exec sp_addrolemember N'SQLAgentUserRole', N'some_user'; go exec sp_addrolemember N'SQLAgentOperatorRole', N'some_user'; go Below is the C# code you can use. If you have a Visual Studio then create a Console application named MonthlyExtractExecutor and then add a reference to System.Configuration. Paste the code below into it: using System; using System.Configuration; using System.Data; using System.Data.SqlClient; using System.IO; namespace MonthlyExtractExecutor { class Program { static void Main(string[] args) { string filePath = ConfigurationManager.AppSettings["filePath"]; string connection = ConfigurationManager.ConnectionStrings["main"].ConnectionString; try { // First step is to access the file located in the shared folder on network // The Active Dirtectory user running this program must have access to it Console.WriteLine("Trying to access the file, please wait..."); using (StreamReader reader = new StreamReader(filePath)) { // read the first line from the file, it should contain the call to execute sp_start_job proc Console.WriteLine("Reading the first line in the file, please wait..."); string sql = reader.ReadLine(); // try to open connection and then execute the job. For this to succeed, the following must happen: // The user (the one specified with user id and password in the config file) has to // be a valid user in msdb database // be granted the SQLAgentUserRole and SQLAgentOperatorRole database roles in msdb database using (SqlConnection cn = new SqlConnection(connection)) { Console.WriteLine("Trying to open connection, please wait..."); cn.Open(); using (SqlCommand cm = new SqlCommand()) { cm.Connection = cn; // generally speaking, it would be better to specify the command type as StoredProcedure, // provide the name of the procedure and pass parameters, but the code below is used just // to create a scenario from the original question cm.CommandType = CommandType.Text; cm.CommandText = sql; Console.WriteLine("Trying to execute the procedure to start the job, please wait..."); cm.ExecuteNonQuery(); } // command object instance is disposed cn.Close(); } // connection instance is disposed :) reader.Close(); } // reader is disposed } catch (Exception ex) { Console.WriteLine("Error Message: " + ex.Message); Console.WriteLine("\r\n\r\nStack Trace: " + ex.StackTrace); } Console.WriteLine("All done, please press any key to end."); Console.ReadLine(); } } } Before running the application, please add the connection string details and path to the sql file to the app.config file. If the solution explorer in Visual Studio does not show that the app.config file is already there then add new item -> application configuration file from the right-click menu of the project: If you compile and run the application, it will do what sqlcmd was meant to do, but it will let you kinda debug it by spelling out what it is doing step by step and bailing out if any error occurs. Because it is a .NET app, it does not really need any installation package. You can just have the user to login to her computer, copy the contents of the bin\\Debug folder to it and then have her to double-click on the executable file to run the job. This will complete if all is well and write out the error information if something is wrong. For example, if the SQL user does not have membership roles in msdb database then you will get the error stating the job named Monthly extract does not exist. If the user or password or server info is incorrect then it will tell you that the connection to the server could not be established or login failed. If the Active Directory User who is running the app does not have permissions to the file then you will see this error information. Please let me know if this helps. Oleg **End Edit** --\>
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

paws27284 avatar image paws27284 commented ·
Hi Oleg, To ensure permissions were granted I created a specific folder for the user and gave her full control once I shared it. She is the only user able to access it. I was able to gain access using the full path to the specific folder from her desktop in Windows explorer. So I tried again and got the Access Denied error on the log file in the above script using -o SQLCMD option. I tried executing it without the -o option and received a different error. It stated "Could not open a connection to SQL server sqlcmd: error: A network related or instance specific error has occurred while establishing a connect to sql server. Server is not found or not accessible. check if instance name is correct and if sql server is configured for remote access." The server name is correct and it is configured for Remote access. Other suggestions?
0 Likes 0 ·
paws27284 avatar image
paws27284 answered
Hi Oleg, To ensure permissions were granted I created a specific folder for the user and gave her full control once I shared it. She is the only user able to access it. I was able to gain access using the full path to the specific folder from her desktop in Windows explorer. So I tried again and got the Access Denied error on the log file in the above script using -o SQLCMD option. I tried executing it without the -o option and received a different error. It stated "Could not open a connection to SQL server sqlcmd: error: A network related or instance specific error has occurred while establishing a connect to sql server. Server is not found or not accessible. check if instance name is correct and if sql server is configured for remote access." The server name is correct and it is configured for Remote access. Other suggestions?
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Oleg avatar image Oleg commented ·
@paws27284 It looks like the permission to the file was an issue and it is now resolved. Because the latest error message reads that the server name is invalid then it means that either the server name is not spelled correctly or the instance cannot be accessed by name (actually, it has to be the instance name not the server name, which just happens to equal the server name only if the default, not named instance of the SQL Server is installed and configured). You can try to open SSMS and connect to this instance using the instance name, user name and password. If this does not work then please check the instance name. Sometimes it is possible that the server name and instance name don't match (if the server was renamed after SQL Server was already installed): select @@servername; select serverproperty('ServerName'); Both statements should return the same value.
0 Likes 0 ·
paws27284 avatar image
paws27284 answered
HI Oleg, I appreciate you getting back to me so quickly. I don't believe permission to the log file was resolved, I removed the reference to the log file, so it is not accessed at all. In this case the server name and instance name are the same. I executed the suggested sql commands and the result is both statements returned the same value. I can connect to the database via SSMS using the login and password I am passing in the SQLCMD within the bat file. My goal is to NOT add the user who initiates the bat to SQL Server. Maybe I create a "generic" user in sql and set it to only initiate Stored Procedures via the execute command? Is that even possible? Maggie
2 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Oleg avatar image Oleg commented ·
@paws27284 Yes, it is possible to create a user in the database which does not have any permissions except to execute the specified procedure(s). In SSMS on the server level, create a login. This login will be a member of the public role, which does not yet grant any permissions to any database (except the permission to login). After that, from the context of the specific database, create a user from that login. This will place the user to be a member of the database public role which does not grant any other permissions. If you then grant explicit permission to that user to execute a specific procedure then the user will not be able to do anything except executing the procedure. For example, if the procedure selects from the join of 2 tables and then inserts the results to the third table, the user will not be able to select from any of the 2 tables, nor she will be able to insert any data. However, the user will be able to execute the procedure. My apologies if you already know all that and I still some up with the long explanation. I will continue in the next comment.
0 Likes 0 ·
Oleg avatar image Oleg commented ·
@paws27284 The big question is what happens when you try to execute the same procedure using these methods: Login to SSMS using SQL authentication with the user id and password same as in that batch file and then run execute msdb.dbo.sp_start_job @job_name = 'Monthly Extract' Does the script above run? If not then the error message might give you some indication about what is wrong. Login to your own computer and then run the original batch file. What happens? Login to your computer, modify the batch file to use the more powerful user id and password and then run it. What happens?
0 Likes 0 ·
paws27284 avatar image
paws27284 answered
Hi Oleg, I have success in all of the suggestions above using the bat file user id and password and using my user id and password. I also have success when executing the whole concept on my desktop, which is why I thought it would work for the user. However since I am both the SQL DBA and the Server Admin I have enough access for the bat file to work. Any other thoughts or suggestions would be appreciated, but will default to the idea above if nothing else. Thanks and Merry Christmas! paws
1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Oleg avatar image Oleg commented ·
@paws27284 I will add some code and comments to my answer in few minutes (cannot do it here due to space limit), hopefully it will help you to figure out the source of the problem. Merry Christmas! Oleg
0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.