Wednesday, 19 March 2014

Execute SQL script file in C#

I was faced with the challenged of executing an SQL batch script from my C#code.

As is always the case, I started by using the SqlCommand object to run it, to which I received an exception on the ‘GO’ statements in my script. The next step was to parse the script and remove the ‘Go’ keyword which didn’t work because the script was at some point creating Stored procedures and executing them.

Here is how I fixed my problems..

Since Sqlserver 2005, it is possible to  reference SMO library in your project.
Refence the following files in the your project
  1. Microsoft.SqlServer.ConnectionInfo.dll
  2. Microsoft.SqlServer.Management.Sdk.Sfc.dll
  3. Microsoft.SqlServer.Smo.dll
Copy paste following code snipet to your project. Edit it to fit your intended use
using System.IO;
using System.Data.SqlClient;
using Microsoft.SqlServer.Management.Smo;
using Microsoft.SqlServer.Management.Common;

public class SQLEngine
{
public static void ExecuteScript()
{
LogFile logFile;
SqlConnection Sqlconnection;
Server server=null;
string SQLscript;
FileInfo file;
try
{

file = new FileInfo("C:\\script.sql");
SQLscript = file.OpenText().ReadToEnd();

Sqlconnection = "Data Source=(local);Initial Catalog=[Catalog];Integrated Security=True
ServerConnection serverConnection = new ServerConnection(Sqlconnection);
server = new Server(serverConnection);

server.ConnectionContext.InfoMessage+=new SqlInfoMessageEventHandler(myConnection_InfoMessage);

server.ConnectionContext.BeginTransaction();

server.ConnectionContext.ExecuteNonQuery(SQLscript); // hangs here for about 7 -15 seconds

server.ConnectionContext.CommitTransaction();

server.ConnectionContext.InfoMessage -= new SqlInfoMessageEventHandler(myConnection_InfoMessage);

}
catch (Exception ex)
{
//Handle Exception
}

}


private static void myConnection_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
//Add code to manage the messages
}

}

Incase you are using .NET 2 version of Microsoft.SqlServer…dll, while your project targets a higher version. You are likely to get this error;

System.IO.FileLoadException was unhandled HResult=-2146232799 Message=Mixed mode assembly is built against version 'v2.0.50727' of the runtime and cannot be loaded in the 4.0 runtime without additional configuration information.

Change the app.config file and add the following to allow loading of .net 2 assemblies

<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
<requiredRuntime version="v4.0" />
</startup>


Thursday, 7 November 2013

You don’t always need a Transform file

 

A while back I posted about creating a Transform file to help you install the advertised applications in an MSI. This is a great effort and I would advice anyone to use the method, however we do like taking shortcuts sometimes.

On this post am going to show you how to edit the MSI to automatically install the applications you want without having to create a Transform file.

 

Method One

1. Start by opening the MSI using orca as stated in the previous blog.

2. Navigate gate to the  the Features table.

3. Change features you want to install on level column from 4 to 3 and save.

Editleveljpg

4. When you execute the MSI file you will realise that the feature is automatically selected for installation.

 

 

Method TWO

This is another crooked method where you change the features from the original Parent to the one selected as default install.

1. Follow step one and two in method one above.

2. Select the FeatureComponent table and sort the table by Features column.

3. Spot the components of the application you want to install and change the Feature column to the name of the default feature.

Example

FeatureComponents

In the diagram above, assuming we are installing Visual studio, and we want to install ‘Crystal report’ as part of ‘Visual_Studio.NET_Enterprise’, I will change the feature column of all the rows reading 'Crystal_Reports’ to Visual_Studio.NET_Enterprise’. This makes crystal report part of the .NET enterprise and it will be installed automatically without having to select it.

Note: Make sure you keep a backup of the original MSI just incase.

Enjoy your install

Wednesday, 19 December 2012

Extracting contacts from a .sbu file

A while Back I had my Galaxy phone stolen to which I later bought a new one. However the problem was that the backup I had from the previous phone was in a .sbu file which I could not open or restored using the Kies application. After many tries and Googling, I came across this source edited it the used it to extract the contacts(VCARD data) from the SBU file.
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

public class SSVCardExtractor {

    private static final String VCARD_FILE_SUFFIX = ".vcf";

    private String outputCharset = "ascii";

    private String inputCharset = "UTF-16LE";

    private InputStream input;

    private VCardWriter output;

    private byte[] start;

    private byte[] end;

    private interface VCardWriter {

        public void write(String vcard) throws IOException;

    }

    public SSVCardExtractor(String inputPath, String outputPath,

            boolean separate, boolean suffixFix) throws IOException {

        if (!separate && suffixFix && !outputPath.endsWith(VCARD_FILE_SUFFIX)) {

            outputPath = outputPath + VCARD_FILE_SUFFIX;

        }


        final File outputFile = new File(outputPath);

        if (outputFile.exists()) {

            throw new IOException("Output path exists: " + outputFile);

        }

        if (separate) {

            outputFile.mkdirs();

            this.output = new VCardWriter() {

                private File directory = outputFile;

                private int index = 0;

                @Override

                public void write(String vcard) throws IOException {

                    File file = new File(directory, ++index + VCARD_FILE_SUFFIX);

                    FileOutputStream stream = new FileOutputStream(file);

                    try {

                        stream.write(vcard.getBytes(outputCharset));

                        stream.flush();

                    } finally {

                        stream.close();

                    }

                }

            };

        } else {

            final String outputPathCopy = new String(outputPath);

            this.output = new VCardWriter() {

                private OutputStream stream = new FileOutputStream(

                        outputPathCopy);

                @Override
                public void write(String vcard) throws IOException {

                    stream.write(vcard.getBytes(outputCharset));

                    stream.flush();

                }


                protected void finalize() throws Throwable {

                    try {

                        stream.close();

                    } catch (Exception e) {

                        // pass

                    }

                }

            };

        }

        this.input = new BufferedInputStream(new FileInputStream(inputPath));

        this.start = "BEGIN:VCARD".getBytes(inputCharset);

        this.end = "END:VCARD".getBytes(inputCharset);

    }

    public void extract() throws IOException {

        while (skipUntil(start, false) != null) {

            byte[] data = skipUntil(end, true);

            if (data == null) {

                throw new IOException("Unexpected end of stream");

            }

            String vcard = new String(start, inputCharset)

                    + new String(data, inputCharset) + "\r\n";

            output.write(vcard);

        }

    }

    private byte[] skipUntil(byte[] bytes, boolean store) throws IOException {

        int searchPosition = 0, current;

        ByteArrayOutputStream data = new ByteArrayOutputStream();

        while ((current = input.read()) >= 0) {

            if (store) {

                data.write(current);

            }

            if ((byte) current == bytes[searchPosition]) {

                if (++searchPosition == bytes.length) {

                    return data.toByteArray();

                }

            } else if (searchPosition != 0) {

                searchPosition = 0;

            }

        }

        return null;

    }


    private static void usageExit(String message) {

        PrintStream out = System.out;

        if (message != null) {

            out.println(message);

        }

        out.println("Usage: java SSVcardExtractor [OPTIONS] <SBU-FILE> <OUTPUT-PATH>");

        out.println("Options:");

        out.println(" -s, --separate       Write each vcard to separate file.");

        out.println("                      By default all vcards are written to one file.");

        out.println("     --no-suffix-fix  Do not add missing "

                + VCARD_FILE_SUFFIX + " suffix.");

        out.println("     --debug          Print debug messages.");

        out.println("     --accept-license Accept license.");

        System.exit(1);

    }

    public static void main(String[] args) {

        boolean separate = false;

        boolean debug = false;

        boolean suffixFix = true;

        boolean acceptLicense = false;

        List<String> arguments = new ArrayList<String>(2);

        for (String argument : args) {

            if (argument.equals("--separate") || argument.equals("-s")) {

                separate = true;

            } else if (argument.equals("--debug")) {

                debug = true;

            } else if (argument.equals("--no-suffix-fix")) {

                suffixFix = false;

            } else if (argument.equals("--accept-license")) {

                acceptLicense = true;

            } else if (argument.startsWith("-")) {

                usageExit("Invalid option: " + argument);

            } else {

                arguments.add(argument);

            }

        }

        if (arguments.size() != 2) {

            usageExit("Invalid argument count");

        }

        try {

            SSVCardExtractor extractor = new SSVCardExtractor(arguments.get(0),

                    arguments.get(1), separate, suffixFix);

            extractor.extract();

            System.out.println("Extract Complete...");

        } catch (IOException e) {

            System.out.println(e.getMessage());

            System.out.flush();

            if (debug) {

                e.printStackTrace();

            }

        }

    }

}






The SBU file is some kind of uncompressed archive file with UTF-16 encoding, all that this code does is to find the VCard start and End tags then writes the VCard items into a file. I then used the generated file to import the contacts to my phone.


How do you use the program?


1. Make sure you have java installed in your machine

2. Copy the code and paste it in a notepad, save the notepad as SSVCardExtractor.java

3. Copy the SBU file in the java bin folder “Program files/java/jdk1.6.0_25/bin”

4. Start the command window

5. Compile the program above as shown;
javac

6. Execute the program to extract the 20121120T112151.sbu which was my backup as follows;

java SSVCardExtractor 20121120T112151.sbu output.vcf

the extract file will be output.vcf

7. You can now use Kies to import the contacts from output.vcf file to your phone.


The Java sdk may be located on a different path on you computer, please confirm that.

Monday, 29 October 2012

Patch Installation error

I ran into a sticky situation while trying to apply a second patch to an application but failed, instead getting an error. The actual scenario was that my product was version 2.0 which was already patched with version 2.1, applying patch 2.2 failed but when patched directly with 2.2, it upgraded successfully.

This is the upgrade error I received while patching;

"The upgrade patch cannot be installed by the Windows Installer service because the program to be upgraded may be missing, or the upgrade patch may update a different version of the program. Verify that the program to be updated exists on your computer and that you have the correct upgrade patch."

Notice the error number is missing, that a fail to installshield.

Among other,s the reason why this error occurs is because the application to upgrade is either not installed, the Upgrade code has changed or the previous patch Package code may be similar to the new patch. In my case I discovered that the patch 2.1 was somehow changing the upgrade code making it impossible for the 2.2 patch to install.

My solution to this issue was to change the Transform Filter Settings on the previous packages page. I changed the ‘Match Upgrade Code’ setting to “NO” and left the “Match Product Code” setting as ‘YES’ this would make sure that the patch only upgrades the product version it is supposed to leaving out the upgrade code validation. This may be a crude method but it fixed my issue in the nick of time.

Here is an image to demonstrate.

image