Software tips

Random programming tips and tricks

Using the DTSRunDec tool

clock April 22, 2008 09:24 by author notjordan

Heres a scenario: Your given a SQL database with a set of scheduled jobs and need to find out exactly what these jobs do. You begin running into a problem when all of the DTS steps look like this:

Notice the DTSRun parameters were encrypted with the dtsrunui tool. The good news is that most anything that can be encrypted and distributed can be decrypted. Fortunately a tool already exists to handle decrypting this text.
Visit SqlSecurity http://www.sqlsecurity.com/Tools/FreeTools/tabid/65/Default.aspx
and download the "DTSRunDec" zip file.
File contents:
build.cmd
DTSRunDec2.c
DTSRunDec.c
readme.txt

Note: You will need Visual Studio to compile this tool, or search the web for a pre-compiled version. Compile by navigating the visual studio command prompt to the unzipped files and running build.cmd.

Drop the newly compiled executables in a directory that is accessible from your PATH and you are ready to start decrypting.
Decrypt a string by copying the text that follows "DTSRun /~Z" into your command window as shown below.

DTSRunDec should give you a clear readable version of the parameters.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Classic ASP data access using parameterized SQL

clock April 20, 2008 01:05 by author notjordan

Been doing a bit of classic ASP again lately, so thought I'd write up one of my opinions on a best practice for ADO.
Contrary to what seems like popular belief, classic ASP provides objects to allow building of parameterized SQL statements. Thats right, you don't HAVE to concatenate a SQL statement in a string, you can use the ADODB.command object instead.
Be sure to #include adovbs.inc to have access to the constants referenced below.

Returning a Recordset:

        With oSQLCommand
            .ActiveConnection = oSQLConn
            .CommandText = "usp_storedProcName"
            .CommandType = adCmdStoredProc
            'add input parameters
            .Parameters.Append .CreateParameter("@TableId", adInteger, adParamInput, , iTableIdValue)
        End With
        'run the stored procedure
        oRS.Open oSQLCommand

Returning OUTPUT parameters:

        With oSQLCommand
            .ActiveConnection = oSQLConn
            .CommandText = "usp_storedProcName"
            .CommandType = adCmdStoredProc
            'add input parameters
            .Parameters.Append .CreateParameter("@sFieldName", adVarChar, adParamInput, 20, sFieldValue)
            'add output paramters
            .Parameters.Append .CreateParameter("@iOutput", adInteger, adParamOutput, , 0)
            'run the procedure and save the output
            .Execute, , adExecuteNoRecords
            iReturnedValue = .Parameters("@iOutput")        
        End With

Not using a stored procedure? Remove the CommandType, and put parameters in the WHERE clause:

        With oSQLCommand
            .ActiveConnection = oSQLConn
            .CommandText = "SELECT * FROM whatever WHERE field1=@field1"
            'add input parameters
            .Parameters.Append .CreateParameter("field1", adInteger, adParamInput, , iTableIdValue)
        End With
        'run the stored procedure
        oRS.Open oSQLCommand

Using the Command object may introduce it's own downsides, but it is certainly better than the way that some people still do data access in ASP:
"SELECT * FROM whatever WHERE field1='" & Replace(sField1Value, "'", "''") & '"

Aside from the fact that a list of named Parameter objects inside of a Command object being much easier to debug than a long concatenated string, a parameterized Command object will also be safer. Many people will argue that simply replacing single quotes will solve all SQL injection problems, but there are other vulnerabilities left open by bad coding practices. Yes, Yes I'm sure the code you write is perfect, but for the sake of argument lets say you inherited a project that someone else wrote with the following code and slack database permissions:
'hiddenId is assumed to be an integer, and is posted to the current page in a hidden form field.
iIntIdValue = Request.Form("hiddenId")
'previous developer did not put single quotes around the identifier since it should always be an integer
"SELECT * FROM whatever WHERE intIdentifier=" & Replace(iIntIdValue, "'", "''") & " Order by orderField"
Simply changing the hidden field's value to "1;TRUNCATE TABLE whatever--" before post will cause some nasty results if database permissions are not properly set. Of course nobody would be using a login that has TRUNCATE permission on a table with a production server right? Even if the database permissions are locked down fairly tightly then the user could still write an UPDATE or INSERT statement to change information in open tables.

Now lets assume you always use parameterized stored procedures AND replace single quotes. The above problem can still exist assuming the LAST parameter in the stored procedure call is a numeric value that is not wrapped in single quotes:
'hiddenId is assumed to be an integer, and is posted to the current page in a hidden form field.
iIntIdValue = Request.Form("hiddenId")
'previous developer did not put single quotes around the identifier since it should always be an integer
"usp_DoStuffToWhatever '" & Replace(sSomeVarCharValue, "'", "''") & "', " & Replace(iIntIdValue, "'", "''")
Changing the hidden field's value before post to "1;TRUNCATE TABLE whatever" will cause the stored procedure to run, then the second query will run.

The above examples are far from being advanced injection tactics, but I have seen the problem in practice, and thats more than enough to wreak havoc on the production databases.

Some good references for the Command and Parameter objects: (forget MSDN)
http://www.w3schools.com/ado/ado_ref_command.asp
http://www.w3schools.com/ado/ado_ref_parameter.asp

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Using a DWL G820 to bridge two wireless routers

clock April 10, 2008 03:51 by author notjordan


After using this product for a month I was ready to write a bad review and bash it to pieces. The occasional engrish, and very inconsistent performance was frustrating, but then again I really wasn’t using the product as it was intended to be used. My wireless router does not have an internet connection, so I was using a DWL G820 to bridge my SMC router to another wireless router that did have an outside connection. The DWL G820 worked great when I had it connecting to a single computer, but when connected to my router it barely worked for a few days, and then quit working completely.

Since the device worked fine when connected to a single computer I decided to give configuration a second chance before hitting it with a hammer. Here are the steps I followed to use this device as a wireless bridge between two routers:

  • Connect the DWL G820 to a computer via crossover cable.
  • Manually set the IP of the computer to 192.168.0.XXX and browse to 192.168.0.35 to manage the device.
  • Configure the DWL G820 to connect to the appropriate wireless network, and change the default password.
  • Set the computer to DHCP so that it may automatically retrieve an IP address from the router that you connected to with the bridge.
  • Test the connection by browsing to a website to make sure that the bridge is working.
  • Now plug the DWL G820 into the WAN port of the router, and open up advanced configuration for the router.
  • DHCP was not working when I plugged my DWL G820 into the router, so configure the router to use a static IP that is in the range of the wireless router that you are connecting to. On mine the settings were: IP-192.168.1.XXX, Gateway-192.168.1.1.

Before following the above steps I tried using a regular ethernet cable, and about every possible configuration setting on the router with very poor/inconsistent results. I now have 1 week of flawless performance, which is looking much better than the few hours of usable connection I had before. Most of the complaints I read about the bridge can be blamed on user error, although I do think they could have made it easier to configure without having to jump through a hoop. Some people have reported it overheats easily, but so far I have had no trouble with that. For $29 after rebate this bridge has served as a good cheap component to handle my needs, and should work great for anyone looking to use it how it was originally intended.

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Improve system performance using batch scripts

clock April 7, 2008 01:32 by author notjordan

*Note: The batch scripts below were created for Windows XP.
Many people will usually end up using one computer to handle most everything, so you can imagine how much software gets installed and how sluggish it can get. With everything that starts automatically my laptop easily pushes 800MB of RAM usage after startup.

Many processes that are enabled by default are not used all the time; in fact I rarely use many of the ones on my laptop. One way to trim down the load on a computer without having to completely remove software is to setup scripts to manually start/stop processes as needed.

Step 1: Identify categories to group rarely used processes under
Categories for my computer:

  • IIS, ASP.NET development
  • PHP, apache development
  • Cold fusion development
  • Proxy services (Tor/Privoxy)

 

Step 2: Find executables and processes that are started automatically for each category
This step is a bit of trial and error; focus on a few at a time because finding dependencies for a large number of processes would not be fun.
-Set each relevant service to “Manual” startup.
-Remove each relevant executable from automatically starting up.

Step 3: Create a batch script for each category
Place commands to start/stop each process and executable from step 2 into a batch file.
The following are provided as an example, they may need modification for other installs.

IIS.bat:

@echo off
set x="%1"
set y="%2"
IF %x%=="start" (
net start "SQL Server (SQLEXPRESS)"
net start "SQL Server Browser"
net start "SQL Server FullText Search (SQLEXPRESS)"
net start "SQL Server VSS Writer"
net start "Simple Mail Transfer Protocol (SMTP)"
net start "World Wide Web Publishing"
net start "IIS Admin"
net start ".NET Runtime Optimization Service v2.0.50727_X86"
) ELSE IF %x%=="stop" (
net stop "SQL Server (SQLEXPRESS)"
net stop "SQL Server Browser"
net stop "SQL Server FullText Search (SQLEXPRESS)"
net stop "SQL Server VSS Writer"
net stop "Simple Mail Transfer Protocol (SMTP)"
net stop "World Wide Web Publishing"
net stop "IIS Admin"
net stop ".NET Runtime Optimization Service v2.0.50727_X86"
) ELSE (
echo Valid Options:
echo start
echo stop
);
IF %y%=="nopause" (
echo Done with apache.bat
) ELSE (
pause
)

apache.bat:

@echo off
set x="%1"
set y="%2"
IF %x%=="start" (
start "httpd" httpd.exe
start "ApacheMonitor" /Dc:\"Program Files"\"Apache Software Foundation"\Apache2.2\bin /B ApacheMonitor.exe
net start "mysql"
) ELSE IF %x%=="stop" (
tskill ApacheMonitor
tskill httpd
net stop "mysql"
) ELSE (
echo Valid Options:
echo start
echo stop
);
IF %y%=="nopause" (
echo Done with apache.bat
) ELSE (
pause
)

cf.bat:

@echo off
set x="%1"
set y="%2"
IF %x%=="start" (
net start "ColdFusion 8 .NET Service"
net start "ColdFusion 8 Application Server"
net start "ColdFusion 8 ODBC Agent"
net start "ColdFusion 8 ODBC Server"
) ELSE IF %x%=="stop" (
net stop "ColdFusion 8 .NET Service"
net stop "ColdFusion 8 Application Server"
net stop "ColdFusion 8 ODBC Agent"
net stop "ColdFusion 8 ODBC Server"
) ELSE (
echo Valid Options:
echo start
echo stop
);
IF %y%=="nopause" (
echo Done with coldfusion
) ELSE (
pause
)

tor.bat:

@echo off
set x="%1"
set y="%2"
IF %x%=="start" (
start "vidalia" /Dc:\"Program Files"\vidalia /B vidalia.exe
start "privoxy" /Dc:\"Program Files"\privoxy /B privoxy.exe
start "pg2" /Dc:\"Program Files"\PeerGuardian2 /B pg2.exe
) ELSE IF %x%=="stop" (
tskill privoxy
tskill vidalia
tskill tor
tskill pg2
) ELSE (
echo Valid Options:
echo start
echo stop
);
IF %y%=="nopause" (
echo Done with apache.bat
) ELSE (
pause
)

Step 4: Create scripts to start and stop all at once
Add a reference to each of the above batch files into a master batch that can be used for starting/stopping all at once.
startall.bat:

@echo off
start /B apache start nopause
start /B tor start nopause
start /B iis start nopause
start /B cf start nopause
pause

killall.bat:

@echo off
start /B apache stop nopause
start /B tor stop nopause
start /B iis stop nopause
start /B cf stop nopause
pause

Place these batch files into a folder that is within your PATH so they can be executed using Start->Run. I prefer keeping these and other random command tools in a central location that has been added to my PATH variable.
C:\cmdtools

Start->Run commands to START services:

iis start
apache start
cf start
tor start
startall

Start->Run commands to STOP services:

iis stop
apache stop
cf stop
tor stop
killall

The difference is quite dramatic on my laptop; RAM usage drops 418MB, with 19 fewer processes running at startup.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Set MasterType to Reference Properties and Controls of the Master Page

clock November 18, 2007 03:59 by author notjordan

Add the following declaration to content pages to allow easy access to master page public properties and controls.
<%@ MasterType VirtualPath="~/MasterPageName.master"%>
This will allow you to reference a public property or control by making a call like “me.master.PropertyName”. Extra code to cast would be needed if you did not specify the MasterType.

MasterType can also be set when using nested master pages, but you will not be able to reference the top master's controls without creating a public property for each.
Setup nested master pages as shown below.

<%@ Master Language="VB" CodeFile="MasterPageInner.master.vb" Inherits="MasterPageInner" MasterPageFile="~/MasterPageOuter.master"%>
<%@ MasterType VirtualPath="~/MasterPageOuter.master"%>

<asp:Content ContentPlaceHolderID="ContentOuter" runat=server>
    <asp:contentplaceholder id="ContentInner" runat="server">
    </asp:contentplaceholder>
</asp:Content>

Content page:

<%@ Page Language="VB" MasterPageFile="~/MasterPageInner.master" AutoEventWireup="false" CodeFile="MasterTypeTest.aspx.vb" Inherits="MasterTypeTest" title="Untitled Page" %>
<%@ MasterType VirtualPath="~/MasterPageInner.master" %>
<%@ Reference VirtualPath="~/MasterPageOuter.master" %>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentInner" Runat="Server">
    <asp:Literal ID="LitTest" runat="server"></asp:Literal>
</asp:Content>

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Performance Tip-Use StringBuilder

clock November 10, 2007 05:22 by author notjordan

String concatenation is not efficient in .NET because Strings are immutable. Changes made to a String cause a new copy of the String to be created, resulting in unnecessary overhead for each operation and extra garbage waiting to be collected. This can result in very noticeable performance loss especially when looping.
Make use of the StringBuilder class when concatenating a String instead of adding to a String object. There is some overhead when creating a StringBuilder, but this overhead is offset after about five operations. Make a habit of using the StringBuilder class when five or more operations are expected to be done on the String.

Below is a short speed test to see how dramatic of a difference there can be when looping.

Code-behind:

Dim dateStart As DateTime
Dim dateEnd As DateTime
Dim timeDiff As TimeSpan

'Run for regular string concat-------------
Dim strRegular As String = ""
dateStart = Date.Now
For i As Integer = 0 To 15000
strRegular = strRegular + i.ToString
Next
dateEnd = Date.Now
timeDiff = dateEnd - dateStart
Me.LitSRegular.Text = timeDiff.ToString
'------------------------------------------
'Run for stringbuilder---------------------
Dim strbTest As New StringBuilder()
dateStart = Date.Now
For i As Integer = 0 To 15000
strbTest.Append(i.ToString)
Next
dateEnd = Date.Now
timeDiff = dateEnd - dateStart
Me.LitSBuilder.Text = timeDiff.ToString
'------------------------------------------

Front-end:

Regular string concatenation: <asp:Literal ID="LitSRegular" runat="server"></asp:Literal>
<br />
StringBuilder: <asp:Literal ID="LitSBuilder" runat="server"></asp:Literal>

Running the above code will provide similar results to the following:
Regular string concatenation: 00:00:01.8281250
StringBuilder: 00:00:00.0156250

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


Search

Categories


Tags



Blogroll

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010

Sign in