Wednesday, May 16, 2012

Calling a user-defined Sql Server function from VBScript using ADO and ODBC

In this script, I call a scalar function written for Sql Server 2005.
This script was tested in Windows Server 2008.
I use VBScript, ADO and ODBC to make this call.
This scalar function is called IsIpBlocked
It has only one parameter, which is of varchar type.
The return value, which is read and printed from this script, is of bit data type.
Therefore, if 1 is returned "true" is printed else if 0 is returned "false" is printed, and if null is returned "false" is printed.
I saved this file with a vbs extension.
Later, I called this file from the command prompt.
I saved this file as udf.vbs, so to execute this script, from the command prompt I executed:

wscript udf.vbs 127.0.0.1

The ip address you see, is an argument passed to this script, which is turn is passed as a parameter to this scalar function.
This script is shown as follows:


set cn = CreateObject("ADODB.Connection")
set cmd = CreateObject("ADODB.Command")
cn.open "Driver={SQL Native Client};Server=your_server;Database=your_database; Trusted_Connection=yes;"
Set cmd.ActiveConnection = cn
cmd.CommandText = "IsIpBlocked"
cmd.CommandType = 4
' Ask the server about the parameters for this scalar function
cmd.Parameters.Refresh
' Assign a value to the 2nd parameter.
' because this scalar function only has one parameter
' in this case, it is an ip address
' so, its only parameter is varchar data type
' Index of parameter 0 represents return value.
cmd(1) = wscript.arguments(0)
cmd.execute
wscript.echo "the answer is: " & cmd(0)
cn.close()

As an alternative, you can connect to your database in Sql Server, using a Sql login.
This can be achieved with the connection string shown as follows:

"Driver={SQL Native Client};Server=your_server;Database=your_database; Uid=your_username;Pwd=your_password;"

A few more notes: if your scalar function call fails then find out, by asking your Dba, the schema or database owner to which your scalar function belongs to. Typically, it is "dbo", but because of security, architecture, design, etc reasons it might not be "dbo".
Therefore, in my case, I can change line of code from cmd.CommandText = "IsIpBlocked" to cmd.CommandText = "dbo.IsIpBlocked"


Moreover, to change this script from a Windows Administrative script to a Classic Asp script, change "CreateObject" to "Server.CreateObject". You also need to change "wscript.echo" to, for example, "response.write" method call. Finally, change "wscript.arguments" to, for example, "request.querystring" call in case of using get method, or "request.form" call in case of using post method. An example of a Classic Asp script running in Windows 7 or 2008, against a Sql Azure database, is found at http://sqlpoetry.blogspot.com/2010/06/calling-stored-procedure-in-sql-azure.html

Finally, if you need to call a user-defined scalar function with Vb.Net and Ado.Net then please go to http://sqlpoetry.blogspot.com/2009/11/example-of-calling-sql-server-2008-user.html

Good luck,

Tonci Korsano Saavedra

Please, visit my Resume Web Site and my .Net Framework Blog

Monday, May 14, 2012

Reverse Engineer Sql Agent Jobs with C# and Smo

This is a program that will connect to Sql Server 2005 and generate Sql code for its Sql Jobs and write this generated Sql to a text file with a sql extension.
It is a .Net Framework console-driven application written in C# that uses Smo api for this task.
This program logs errors to the Windows Event Log.
This program was tested with .Net Framework 2.0 64-bits, Sql Server 2005 and Windows 2008 Server 64-bits as well.
This program has been tested from the command prompt and also as a Windows scheduled task.
If you want to run this program from the command prompt then right click on command prompt icon and select "Run as Administrator".
If you prefer to run this program as a Windows 2008 server scheduled task then I recommend to make a file with a cmd extension, which will call the executable of this program with its only server name parameter, and next put this path that includes the full path and name of this cmd file in text box of "Program/script:", and in the text box of "Start in (optional):" put the path without the name of this .cmd file.
For references, you need to add the name spaces microsoft.sqlserver.smo, microsoft.sqlserver.connectioninfo and microsoft.sqlserver.management.sdk.sfc.
Followed is the source code of this program:


using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SqlServer.Server;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Agent;
using System.Collections;
using System.Diagnostics;


namespace Sql2005JobsReverseEngineering
{
    class Sql2005JobsReverseEngineering
    {
        const string EventName = "Sql2005JobsReverseEngineering";
        static void Main(string[] args)
        {
            try
            {
                if (!EventLog.SourceExists(EventName, "."))
                {
                    EventLog.CreateEventSource(EventName, "Application");
                }
                if (args.Length != 1)
                {
                    EventLog.WriteEntry(EventName, "Usage: server", EventLogEntryType.Error, 1000);
                    return;
                }


                Server devServer = new Server(args[0]);
                devServer.ConnectionContext.BatchSeparator = "GO";
                string filename = "jobs." + args[0] + "." + DateTime.Now.Year + "." + DateTime.Now.Month + "." + DateTime.Now.Day + "." + DateTime.Now.Hour + "." + DateTime.Now.Minute + ".sql";
                System.IO.StreamWriter sw = new System.IO.StreamWriter(filename, false, Encoding.Unicode);
                System.Collections.Specialized.StringCollection sc = new System.Collections.Specialized.StringCollection();
                ScriptingOptions so = new ScriptingOptions();
                so.IncludeIfNotExists = false;
                so.ScriptDrops = false;
                so.NoCommandTerminator = false;
                so.DriAll = true;
                foreach (Job j in devServer.JobServer.Jobs)
                {
                    sc = j.Script(so);
                    WriteToFile(ref sw, sc);
                }
                sw.Flush();
                sw.Close();
                EventLog.WriteEntry(EventName, "Server " + args[0] + " had its sql jobs reversed engineered to file " + filename, EventLogEntryType.Information);
            }
            catch (Exception ex)
            {
                EventLog.WriteEntry(EventName, ex.Message, EventLogEntryType.Error, 2220);
            }
        }
        static void WriteToFile(ref System.IO.StreamWriter sw, System.Collections.Specialized.StringCollection sc)
        {
            foreach (string str in sc)
                if (str.Contains("SET ANSI_NULLS ON") || str.Contains("SET QUOTED_IDENTIFIER ON") || str.Contains("SET ANSI_NULLS OFF") || str.Contains("SET QUOTED_IDENTIFIER OFF"))
                    sw.Write(str + Environment.NewLine);
                else
                    sw.Write(str);


        }
    }
}

Best regards,

Tonci Korsano

Please, visit my Resume Web Site and my .Net Framework Blog

Tuesday, March 13, 2012

Restart IIS, Sql Server and Sql Agent in C#

This program was made with .Net Framework 2.0 and tested in Windows 2008 Server with Sql Server 2005. It clearly restarts these services well, and if there is an error then you get the stack trace for this error. This is a console-driven application written in C#. When you want to run this application from the command prompt, first right-click on command prompt icon, and next click on "Run as administrator" option. After making this selection, you are ready to run this program from the command prompt by specifying the path to this file with extension exe. The user that logs on the computer that will run this program, must have adequate rights, privileges and permissions to run this program. This program also works well as a windows scheduled task. If this program runs as a scheduled task, it will give feed back by stating in the event log if it succeeds or fails for each service it tries to restart. This program uses smo api to restart Sql Server services. You need to add the following references to be able to compile this program in Visual Studio 2005: microsoft.sqlserver.connectioninfo, microsoft.sqlserver.management.sdk.sfc, microsoft.sqlserver.smo, microsoft.sqlserver.smo.extended, microsoft.sqlserver.sqlenum, microsoft.sqlserver.sqlwmimanagementm microsoft.sqlserver.wmienum

The source code of this program is shown as follows:


using System;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Smo.Wmi;
using Microsoft.SqlServer.Management.Common;
using System.Diagnostics;


namespace RestartSqlAndIis
{
    public class RestartSqlAndIis
    {
        private static Service svc;
        private static Service svcAgent;
        private static ManagedComputer mc;
        const string eventName = "RestartSqlServerAndIis";


        static void Main()
        {


            if (!EventLog.SourceExists(eventName))
            {
                    EventLog.CreateEventSource(eventName, "Application");
            }
            //tks mar.12.2012
            //restart iis in local machine
            try
            {
                using (Process exeProcess = Process.Start(@"C:\windows\system32\iisreset.exe"))
                {
                    exeProcess.WaitForExit();
                }
                Console.WriteLine("IIS was restarted successfully at " + DateTime.Now.ToLongTimeString());
                EventLog.WriteEntry(eventName, 
                    "IIS was restarted successfully at " + DateTime.Now.ToLongTimeString(),
                    EventLogEntryType.Information,
                    1500);


            }
            catch (Exception ex) {
                Console.WriteLine("There was a problem trying to restart IIS in this computer. Error is " + ex.StackTrace);
                EventLog.WriteEntry(eventName ,
                    "There was a problem trying to restart IIS in this computer. Error is " + ex.StackTrace,
                    EventLogEntryType.Error, 1000);
            }


            try
            {
                mc = new ManagedComputer(); /* on the local computer */
                svc = mc.Services["MSSQLSERVER"];
                if (svc.ServiceState == ServiceState.Running)
                {
                    svc.Stop();
                    while (svc.ServiceState == ServiceState.Running)
                    {
                        System.Threading.Thread.Sleep(1000);
                        Console.WriteLine("Sql Server is stopping at " + DateTime.Now.ToLongTimeString());
                        svc.Refresh();
                    }
                    svc.Refresh();
                }
                if (svc.ServiceState == ServiceState.Stopped)
                {
                    Console.WriteLine("Sql Server is known to be stopped at " + DateTime.Now.ToLongTimeString());
                }
                svc.Start();
                while (svc.ServiceState != ServiceState.Running)
                {
                    System.Threading.Thread.Sleep(1000);
                    Console.WriteLine("Sql Server is restarting at " + DateTime.Now.ToLongTimeString());
                    svc.Refresh();
                }
                if (svc.ServiceState == ServiceState.Running)
                {
                    Console.WriteLine("Sql Server was restarted successfully at " + DateTime.Now.ToLongTimeString());
                    EventLog.WriteEntry(eventName,
                        "Sql Server was restarted successfully at " + DateTime.Now.ToLongTimeString(),
                        EventLogEntryType.Information,
                        2500);
                }
                svcAgent = mc.Services["SQLSERVERAGENT"];
                if (svcAgent.ServiceState == ServiceState.Running) 
                {
                    svcAgent.Stop();
                    while (svcAgent.ServiceState == ServiceState.Running)
                    {
                        System.Threading.Thread.Sleep(1000);
                        Console.WriteLine("Sql Server Agent is stopping at " + DateTime.Now.ToLongTimeString());
                        svcAgent.Refresh();
                    }
                    svcAgent.Refresh();
                }
                if (svcAgent.ServiceState == ServiceState.Stopped)
                {
                    Console.WriteLine("Sql Server Agent is known to be stopped at " + DateTime.Now.ToLongTimeString());
                }
                svcAgent.Start();
                while (svcAgent.ServiceState != ServiceState.Running)
                {
                    System.Threading.Thread.Sleep(1000);
                    Console.WriteLine("Sql Server Agent is restarting at " + DateTime.Now.ToLongTimeString());
                    svcAgent.Refresh();
                }
                svcAgent.Refresh();
                if (svcAgent.ServiceState == ServiceState.Running)
                {
                    Console.WriteLine("Sql Server Agent was restarted successfully at " + DateTime.Now.ToLongTimeString());
                    EventLog.WriteEntry(eventName,
                        "Sql Server Agent was restarted successfully at " + DateTime.Now.ToLongTimeString(),
                        EventLogEntryType.Information,
                        2750);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("There was a problem restarting Sql Server in this computer. Error is " + ex.StackTrace);
                EventLog.WriteEntry(eventName, 
                    "There was a problem restarting Sql Server in this computer. Error is " + ex.StackTrace,
                    EventLogEntryType.Error, 2000);
            }
        }
    }
}

Have an excellent day,

Tonci Korsano

Please, visit my Resume Web Site and my .Net Framework Blog 

Tuesday, June 29, 2010

Calling a Stored Procedure in Sql Azure Cloud with Classic Asp from Windows 7




This demonstration was tested with classic asp on Windows 7. Windows 7 is in a laptop, which acts as a development web server, which is connecting to Sql Azure Cloud. This example is only about a html file and a classic asp page. For details on how to acquire an odbc connection string for your databases in Sql Azure cloud, please go to http://sqlpoetry.blogspot.com/2010/06/connecting-to-sql-azure-from-excel-2007.html
Once you have this odbc connection string, you are ready to follow this example. The html code is as follows:


<html>
    <head>
        <title>Calling a Stored Procedure in Sql Azure Cloud with Classic Asp>/title>
    </head>
    <body>
        <form method="get" action="test.asp">
        Introduce a number: <input type="text" name="txtSomething"><br/>
        <input type="submit" name="btnSomehting" value="Click me!">
        </form>
    </body>
</html>

The asp source code is as follows:


   <%
   Set cn = Server.CreateObject("ADODB.Connection")
   Set cmd = Server.CreateObject("ADODB.Command")
   Set rs = Server.CreateObject("ADODB.Recordset")
   'connect by odbc without encryption
   cn.Open "Driver={SQL Server Native Client 10.0};Server=tcp:myServerName.database.windows.net;Database=myDatabase;Uid=myLogin@rwngfgjqka;Pwd=myPassword;Encrypt=no;"
   Set cmd.ActiveConnection = cn
   cmd.CommandText = "getTestTable02"
   cmd.CommandType = 4
   ' Ask the server about the parameters for the stored procedure
   cmd.Parameters.Refresh
   ' Assign a value to the 2nd parameter.
   ' Index of 0 represents first parameter.
   cmd.Parameters(1) = Request("txtSomething")
   Set rs = cmd.Execute
   if rs.eof then
        Response.Write("No records found for " & Request("txtSomething"))
        Response.End()
   else
      do while not rs.eof
        Response.Write(rs(0) & ", " & rs(1) & ", " & rs(2) & "<br/>")
        rs.MoveNext()
      loop      
   end if
   %>

I tested with encrypt attribute of your odbc connection string set to both "yes" and "no", and in both cases testing was successful. Testing also succeeded by setting method attribute of html form tag to both "get" and "post". By coding on Parameters(1), you are setting your first stored procedure parameter, Parameters(2) the second parameter in your stored procedure, etc. By reading Parameters(0), you are getting return value from your stored procedure call. In iis administrator of Windows 7, create a default application pool to be used in the web site, where you will be doing these tests before creating your classic asp web site. Once you have created this application pool, right-click on this application pool, go to "Advanced Settings", and make sure that ".Net Framework Version" is set to "No Managed Code", and that "Identity" is set to "Network Service". After this application pool is created, you are ready to create your web site. I added another web site and used a different port from 80 because Windows 7 comes with a default web site, which is already using port 80. If you find that there are permissions problems accessing com components, set proper permissions to "Network Service" account in "Component Services" management console.
Have an excellent day,
Tonci Korsano
Please, visit my Resume Web Site and my .Net Framework Blog

Thursday, June 24, 2010

Sending dynamic Sql to Sql Azure Cloud from Asp.Net 4.0




I am showing example code, which sends and insert statement and next sends a select statement of the whole table where this insert statement took place. In this scenario, a laptop is connected to the Internet and from development web server of Visual Studio 2010 Beta 2, which is fired once you start debugging, an Asp.Net 4.0 web page sends these two dynamic Sql statements to Sql Azure cloud. As a result of these lines of code, an insert is made in a table of Sql Azure and a grid view is populated. This scenario was tested successfully with Visual Studio 2010 Beta 2, Sql Server 2008 client utilities and Windows 7. The method I am showing as example is called from Page Load event of an Asp.Net web page. This example code is shown as follows:

protected void BindGrid()

        {
            DataSet ds = new DataSet();
            SqlConnectionStringBuilder connstr = new SqlConnectionStringBuilder(System.Configuration.ConfigurationManager.ConnectionStrings["SQLAzureConnection"].ToString());
            SqlConnection conn = new SqlConnection(connstr.ToString());
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter adap = new SqlDataAdapter(cmd);
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.Add("@ip", SqlDbType.VarChar, 15).Value = Request.ServerVariables["remote_addr"].ToString();
            cmd.CommandText = "insert into test_login.test_table values(default, @ip);";
            cmd.Connection = conn;
            conn.Open();
            cmd.ExecuteNonQuery();
            conn.Close();
            cmd.CommandText = "select t.* from test_login.test_table t order by t.id desc;";
            conn.Open();
            adap.Fill(ds);
            conn.Close();
            this.gvw01.DataSource = ds;
            this.gvw01.DataBind();
        }

This example is pretty straightforward, except that SqlConnectionStringBuilder class is used for the connection string to Sql Azure. The object gvw01 is a grid view instance of Visual Studio 2010 Beta 2. You need an Ado.Net connection string to connect to Sql Azure cloud, which in this case is stored in the connection strings section of web.config file. For details on how to get this Ado.Net connection string, visit http://sqlpoetry.blogspot.com/2010/06/connecting-to-sql-azure-from-excel-2007.html which is my blog describing how to acquire these database connections. The only difference on how to get this database connection string between the example of this blog and the example of the referring blog is that you copy an Ado.Net instead of an Odbc connection string.
Best regards,
Tonci Korsano
Please, visit my Resume Web Site and my .Net Framework Blog

Wednesday, June 23, 2010

Connecting to Sql Azure cloud from Excel 2007 and executing a stored procedure with a parameter linked to a spreadsheet cell




I am going to demonstrate how to make a stored procedure call with one parameter from Excel 2007 to Sql Azure cloud. You can read this blog without any previous background in this subject, but I strongly suggest you read my previous blog about Excel 2007 and Sql Azure, which is in the following link http://sqlpoetry.blogspot.com/2010/06/connecting-to-sql-azure-from-excel-2007.html
Let's start by creating a file data source name (dsn) entry, which is odbc based. First, click on the "Add" button,  select "Sql Server Native Client 10.0", and click on "Finish" button, as shown in this image: http://sites.google.com/site/sqlpoetry/dsn.01.jpg
Next, enter a name for your dsn entry, and enter the name of your server, which is specified in your Sql Azure Server Administration web page. Be careful to include your whole dns name for server name, and followed click on "Next" button. The following image illustrates this last procedure: http://sites.google.com/site/sqlpoetry/dsn.02.jpg
Followed, click on "Sql Server Authentication" radio  button, enter Sql Azure login for the intended database, and make sure that the only check box in this step is unchecked after you have entered Sql login and password, and click on "Next" button. Make sure your Sql login includes your server name without the whole dns name. Make sure to pick a Sql login that has as default database precisely the database which contains the stored procedure you intend to call. This is due to the fact that "use" doesn't work in Sql Azure as in other versions of Sql Server. The following image illustrates this last step: http://sites.google.com/site/sqlpoetry/dsn.03.jpg
Followed, click on "Change default database to:" check box, and in the drop down list below this check box, specify the database where the target stored procedure is located. This image shows an example: http://sites.google.com/site/sqlpoetry/dsn.04.jpg
Next, accept all default values, and in the last page of this dsn wizard, test your connection. The next image shows an example of a successful connection: http://sites.google.com/site/sqlpoetry/dsn.05.jpg
At this point, you have a file dsn entry, which is ready to be used to call stored procedures with parameters.
From Excel 2007, click on "Data" tab, click on "From Other Sources", click on "From Data Connection Wizard", which will guide you through this process, select "Odbc Dsn", and click on "Next" button. This following image illustrates part of this process up to selecting "Odbc Dsn": http://sites.google.com/site/sqlpoetry/conn.01.jpg
Followed, pick your file dsn entry that you created for Sql Azure, like in this example image: http://sites.google.com/site/sqlpoetry/conn.02.jpg
Next, accept default values in this wizard until you are taking to "Import Data" window, which is shown in the next image: http://sites.google.com/site/sqlpoetry/conn.03.jpg
Next, click on "Properties" button, click on "Definition" tab, and click on "Edit Query" button, like it is shown in this image: http://sites.google.com/site/sqlpoetry/conn.04.jpg
Surprise because at this point you are in Microsoft Query program, which comes since probably Office 97 or before! Now, click on "Sql" button, like this is shown in next image: http://sites.google.com/site/sqlpoetry/conn.05.jpg
Next, change any Sql text you find in this text box to --> {call your_stored_procedure (?, ?, ...)}  <-- In my case, my stored procedure is called getTestTable02 with only one parameter. Therefore, for my case I entered -->  {call getTestTable02 (?)} <-- as this is shown in the next image: http://sites.google.com/site/sqlpoetry/conn.06.jpg
You will get a message box in which you will click on "Ok" as in this next image: http://sites.google.com/site/sqlpoetry/conn.07.jpg
Followed, you will close "Microsoft Query" program and will be taken to Excel 2007 again. This time you will click on "Definition" tab again, and you will see "Parameters" button enable, which you will click on, like in this illustrating image: http://sites.google.com/site/sqlpoetry/conn.08.jpg
Now, it is time to link your parameters to Excel spreadsheet cells, like I show in the next image: http://sites.google.com/site/sqlpoetry/conn.09.jpg
Once you have related cells to parameters, this window will look like my next presenting image: http://sites.google.com/site/sqlpoetry/conn.10.jpg
Followed, you will click the only check box of this window, which will make your query refresh once cells linked to parameters are changed, like in the following example image: http://sites.google.com/site/sqlpoetry/conn.11.jpg
The next image shows stored procedure output from Sql Azure once the value of 5 is entered in k1 cell: http://sites.google.com/site/sqlpoetry/example.02.jpg
From this point on, changing the value of cell k1, will call the stored procedure set in this blog. If you put in k1 an integer which brings no data, Excel 2007 will show no returning rows as well, like in the next example: http://sites.google.com/site/sqlpoetry/example.03.jpg
I hope you have enjoyed this journey through Sql Azure cloud, Odbc and Excel 2007. Since in this case parameters are linked to spreadsheet cells, these linked cells can be programmed to validate data before a stored procedure is called, with probably only Excel formulas. Besides, part of a required validation can be made in the stored procedure itself. The stored procedure I used for this example is quite simple, but I am showing it.  
create procedure getTestTable02  
@id int  
as    
set nocount on;  
select t.* from test.test_login.test_table t   
where t.id = @id; 
Best regards,

Tonci Korsano

Please, visit my Resume Web Site and my .Net Framework Blog

Connecting to Sql Azure from Excel 2007




I am going to demonstrate how to connect to Sql Azure from Excel 2007, set a time interval in minutes for your query to refresh, call a dynamic select statement from Excel 2007 connection properties, and finally I will show how to call a stored procedure.
The database objects are a database called "test", a Sql Azure login called "test_login", a table called "test_table", and a stored procedure called "getTestTable".
To get the connection string you need, start by login into Sql Azure with your Windows Live username and password, click on the project where your target database is, and at the bottom click on "Connection Strings" button, for Odbc option click on "Copy to Clipboard" link, as shown in these two images:
Followed and in Excel 2007, click on the "Data" tab, click on "From Other Sources" and select "From Data Connection Wizard", select "Other Advanced" and click on "Next", select "Microsoft Ole Db Provider for Odbc Drivers" and click on "Next", click on "Use connection string" radio button, paste your Odbc connection string, within your Odbc connection string place your actual password where ";Pwd=myPassword;" string is located, click on "Test Connection" button, and if this test is successful then you are connecting to your intended database in Sql Azure cloud.
Now and from the list of tables you are shown, select a table from your database and click on "Next" button, like in this image:
At this point, you can select all default options from this wizard, with displaying your selected table in a work sheet as a result.
Now and by starting to click on "Data" tab again, click on "Connections" option of the "Connections" panel, click on "Properties" button, click on "Definition" tab, select "Sql" for the "Command Type" drop down list, enter a select statement in "Command Text" text box, and if your Sql sentence is correct output will be shown in the same work sheet. For an illustration, follow this image:
The same steps can be used to call a stored procedure that returns a record set as output, as shown in this figure:
The source code of this procedure is quite simple and shown as follows:
create procedure getTestTable  
as  
set nocount on  
select row_number() over (order by t.stamped_at) as row_number,   
t.* from test.test_login.test_table t

I found what looks like to be a working timer in intervals of minutes, which can be set in the connection properties of Excel 2007. This image shows where this timer interval can be set:
I made all these tests in Windows 7 and Excel 2007.

Best regards,

Tonci Korsano

Please, visit my Resume Web Site and my .Net Framework Blog