RATCHET

RATCHET Labs

04/14/2011

Running Command Line Bat Files From a Web Page ASP.NET C#

We needed the ability to run some batch processes without having to remote to the server.   I put together a small  ASP.NET app that allowed us to do this.  Found some code for running standard command line application through .NET and modified/extended it to work through a web interface.

Here is the code that does the bulk of the of the work for running the bat files.

public static string ProcessBatFile(string batFile)
{
            string val = "";

            if (!File.Exists(batFile))
            {
                throw new Exception(batFile + " does not exists");
            }

            // Create the ProcessInfo object
            System.Diagnostics.ProcessStartInfo psi =
                    new System.Diagnostics.ProcessStartInfo("cmd.exe");
            psi.UseShellExecute = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardInput = true;
            psi.RedirectStandardError = true;

            // Start the process
            System.Diagnostics.Process proc =
                       System.Diagnostics.Process.Start(psi);

            // Open the batch file for reading
            System.IO.StreamReader strm = proc.StandardError;
            // Attach the output for reading
            System.IO.StreamReader sOut = proc.StandardOutput;

            // Attach the in for writing
            System.IO.StreamWriter sIn = proc.StandardInput;

            // Write each line of the batch file to standard input
            /*while(strm.Peek() != -1)
            {
                sIn.WriteLine(strm.ReadLine());
            }*/
            sIn.WriteLine(batFile);
            strm.Close();

            // Exit CMD.EXE
            string stEchoFmt = "# {0} run successfully. Exiting";

            sIn.WriteLine(String.Format(stEchoFmt, batFile));
            sIn.WriteLine("EXIT");

            // Close the process
            proc.Close();

            // Read the sOut to a string.
            string results = sOut.ReadToEnd().Trim();

            // Close the io Streams;
            sIn.Close();
            sOut.Close();

            val = results;

            return val;
}

I created CMD prompt in CSS to make it look legit. It just displays the captured output from the method above.

This can be extremely unsafe for a server. Your sys admin should question setting something like this up. Please let them know there are steps that can be taken to help make this a safe process such as requiring authentication to access this script and only allow the bat files to run from set directory.

  • Facebook
  • Twitter
  • Digg
  • Print
  • email

02/24/2011

Generate Static Version of a Site with “wget”

It was not that long ago when it was cool to create a dynamic site in Perl, C++, classic ASP, and Cold Fusion (maybe some think it is still cool). What was also cool was to create a static version of the site to run in production. Many projects I worked on would have a fully dynamic staging/preview site and there would be a process to generate static html files from that environment to push to production. This was done to help websites run faster. Apache, IIS were not as good as they are today and if a site had a lot of traffic the dynamic scripts in many cases would not scale.

I recently had a request to create a static version of a dynamic site. I remember there being several 3rd party tools, crawlers, etc out there that were easy to setup/configure.  They would run through a site and generate a nice self contained static version. When I went to look for them I could not find them anywhere. They seemed to have just disappeared. I am assuming that there is just not a demand for them anymore because web servers, languages, and techniques have become so much more efficient.

I still needed to create a static site and I really did not want to write my own crawler/screen scrapper tool. I ran across a command line program called “wget”. It is an older tool but it did exactly what I needed it to do. For a quick test I ran it against labs.ratchet.com. In about 20 minutes I had a static version of the site. The “wget” file generation was not perfect and required some global find/replaces (very easy with notepad++ or Visual Studio) and some manual changes, but the process was not bad at all.

I ran the basic command line tool with the following parameters:

wget --html-extension --convert-links -r http://labs.ratchet.com -P ratchet.com

If you ever need a self contained demo of a site this tool should help get you there. I think it would be handy in a batch or shell script if you needed to connect out to a site to get data or if there were requirements to archive/snapshot sites.

Here are a links to the tool and some posts about

http://gnuwin32.sourceforge.net/packages/wget.htm

http://www.editcorp.com/Personal/Lars_Appel/wget/v1/wget_7.html

http://www.thegeekstuff.com/2009/09/the-ultimate-wget-download-guide-with-15-awesome-examples/#more-1885

  • Facebook
  • Twitter
  • Digg
  • Print
  • email

11/08/2010

Version your CSS and JS File…DO IT!

As a developer working on web applications for the past 12 years I have always had to deal with the questions like “I did not see the change on my browser, was the code updated?”.  The quick response was to clear your browser cache and cookies and restart (maybe only worked about 50% of the time). After several years of going through this process I realized that the “normal” users probably do not know how to do that or what that means.  It would also be strange to have a message on your site after each code push saying “We have updated our site, please clear your browser cache for optimal experience”.  

A very basic way to avoid this issues is to create a new file path which will force the browser to download a new file.  You could rename your files for each code push  styles1-0.css and styles 1-1.css but this can be a pain to maintain. 

The way I have been doing this the last few years is to have the application automatically update the file paths every time the files have actually changed.  This way I do not have to worry about manually setting version with each code push.

Below is a .NET function that will return last modified data stamp of the physical file.  This date stamp becomes the version and gets tacked on at the end of the file with a query string.  I use built in .NET caching so the requests do not have to hit the file each time it loads.

public static string GetIncludeFileVersion(string file)
{
    //check if file exists and get date
    string version = "1.0";
    try
    {
        if (HttpContext.Current != null)
        {
            //always force cache
            if (HttpContext.Current.Cache[file] == null)
            {

                if (File.Exists(HttpContext.Current.Server.MapPath(file)))
                {
                    FileInfo fileInfo = new FileInfo(HttpContext.Current.Server.MapPath(file));
                    if (fileInfo != null)
                    {
                        version = fileInfo.LastWriteTime.ToString("MMddyyyhhss");
                        HttpContext.Current.Cache.Insert(file, version, null,
                        DateTime.Now.AddHours(1), TimeSpan.Zero);
                    }
                }
            }
            else
            {
                version = HttpContext.Current.Cache[file].ToString();
            }

        }
        
    }
    catch (Exception ex)
    {
     //silent for now
    }

    return version;

}

In the ASPX or ASCX or Front end files use the code below for all of your CSS/JS/Images and other include references. You may have to put this into a control depending on how your master/aspx files are setup.

<link type="text/css" href="/library/css/styles.css?<%=Ratchet.Framework.Helper.GetIncludeFileVersion("/library/css/styles.css")%>" rel="stylesheet" />

When your pages render you should see a timestamp version of it. something like

<link type="text/css" href="/library/css/styles.css?102120101114" rel="stylesheet" />

  • Facebook
  • Twitter
  • Digg
  • Print
  • email

10/21/2010

Finding Stored Procedures in SQL

Have an application with 100′s of stored procs and need to find one?  We use this code below that searchs all the stored proc’s syntax in a SQL database.

Create PROCEDURE [dbo].[Find_Text_In_SP]
@StringToSearch varchar(100)
AS
   SET @StringToSearch = '%' +@StringToSearch + '%'
   SELECT Distinct SO.Name
   FROM sysobjects SO (NOLOCK)
   INNER JOIN syscomments SC (NOLOCK) on SO.Id = SC.ID
   AND SO.Type = 'P'
   AND SC.Text LIKE @stringtosearch
   ORDER BY SO.Name

  • Facebook
  • Twitter
  • Digg
  • Print
  • email

10/18/2010

Elmah, Error logging module and handler

We have been using the module for the last few years and have really liked it.  It is easy to setup, log, secure all your unhandled/errors .NET  web applications.

You can find get the code from

http://code.google.com/p/elmah/

  • Facebook
  • Twitter
  • Digg
  • Print
  • email

10/18/2010

Global Permission Set Script for All Stored Procedures

Below is a script that I found that makes it very easy to set execute permissions to all all stored procs in a SQL Server 2005/2008 DB.

-- Set Username
DECLARE @U  sysname ; set @U = QUOTENAME('DB_USERNAME_HERE')
-- Set DB
DECLARE @DB  sysname ; set @DB = 'DB_NAME'
-- SET Schema
DECLARE @schema  sysname ; set @schema = 'SCHEMA_NAME'


DECLARE @ID           integer,
@LAST_ID     integer,
@NAME        varchar(1000),
@SQL         varchar(4000)

SET @LAST_ID = 0

WHILE @LAST_ID IS NOT NULL
BEGIN
SELECT @ID = MIN(id)
FROM dbo.sysobjects
WHERE id > @LAST_ID  AND type = 'P' AND category = 0

SET @LAST_ID = @ID

-- We have a record so go get the name
IF @ID IS NOT NULL
BEGIN
SELECT @NAME = name
FROM dbo.sysobjects
WHERE id = @ID

-- Build the DCL to do the GRANT
SET @SQL = 'GRANT EXECUTE ON ' +@DB + '.' + @schema +'.' + @NAME + ' TO ' + @U

PRINT 'setting execute permissions for: '+  @SQL
-- Run the SQL Statement you just generated
EXECUTE(@SQL)

END


END

  • Facebook
  • Twitter
  • Digg
  • Print
  • email

10/13/2010

SQL Row Count and Table Size Script

Here is a handy little script I found that dumps out all the tables in a SQL DB, their sizes and how many records.  Handy for debugging why your DB has gotten so damn big.

CREATE TABLE #temp (
table_name sysname ,
row_count INT,
reserved_size VARCHAR(50),
data_size VARCHAR(50),
index_size VARCHAR(50),
unused_size VARCHAR(50))
SET NOCOUNT ON
INSERT #temp
EXEC sp_msforeachtable 'sp_spaceused ''?'''
SELECT a.table_name,
a.row_count,
COUNT(*) AS col_count,
a.data_size
FROM #temp a
INNER JOIN information_schema.columns b
ON a.table_name collate database_default
= b.table_name collate database_default
GROUP BY a.table_name, a.row_count, a.data_size
ORDER BY CAST(REPLACE(a.data_size, ' KB', '') AS integer) DESC
DROP TABLE #temp

SQL Row Count and Table Size Script

  • Facebook
  • Twitter
  • Digg
  • Print
  • email