Including MSMQ as a prerequisite for my application - deployment

I'm working on an application that uses MSMQ for interprocess communication, and I need the setup project to be able to install the service if it isn't already. I've checked around for information on making it a prerequisite, but so far I've been unsuccessful at finding this. Any ideas?

Discovered the answer on my own...the windows component installer is not crippled by the typical inability to install more than one MSI at any given time, so I'm able to use a custom installer action to execute a command line script to install MSMQ.
Here's my Installer class (your options may obviously vary):
public partial class MSMQInstaller : Installer
{
public MSMQInstaller()
{
InitializeComponent();
}
[DllImport("kernel32")]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FreeLibrary(IntPtr hModule);
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
bool loaded;
try
{
IntPtr handle = LoadLibrary("Mqrt.dll");
if (handle == IntPtr.Zero || handle.ToInt32() == 0)
{
loaded = false;
}
else
{
loaded = true;
FreeLibrary(handle);
}
}
catch
{
loaded = false;
}
if (!loaded)
{
if (Environment.OSVersion.Version.Major < 6) // Windows XP or earlier
{
string fileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "MSMQAnswer.ans");
using (System.IO.StreamWriter writer = new System.IO.StreamWriter(fileName))
{
writer.WriteLine("[Version]");
writer.WriteLine("Signature = \"$Windows NT$\"");
writer.WriteLine();
writer.WriteLine("[Global]");
writer.WriteLine("FreshMode = Custom");
writer.WriteLine("MaintenanceMode = RemoveAll");
writer.WriteLine("UpgradeMode = UpgradeOnly");
writer.WriteLine();
writer.WriteLine("[Components]");
writer.WriteLine("msmq_Core = ON");
writer.WriteLine("msmq_LocalStorage = ON");
}
using (System.Diagnostics.Process p = new System.Diagnostics.Process())
{
System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo("sysocmgr.exe", "/i:sysoc.inf /u:\"" + fileName + "\"");
p.StartInfo = start;
p.Start();
p.WaitForExit();
}
}
else // Vista or later
{
using (System.Diagnostics.Process p = new System.Diagnostics.Process())
{
System.Diagnostics.ProcessStartInfo start = new System.Diagnostics.ProcessStartInfo("ocsetup.exe", "MSMQ-Container;MSMQ-Server /passive");
p.StartInfo = start;
p.Start();
p.WaitForExit();
}
}
}
}
}

What about the pkgmgr command?
pkgmgr /iu:MSMQ-Container;MSMQ-Server

Thank You!! Here's the VB.Net version for anyone who is interested.
Option Explicit On
Option Strict On
Imports System.Diagnostics.Process
Imports System.IO
Imports System.Text
'Required in all cases when calling API functions
Imports System.Runtime.InteropServices
Imports System.Configuration.Install.Installer
<System.ComponentModel.RunInstallerAttribute(True)> _
Public Class msmqInstaller
Inherits System.Configuration.Install.Installer
Private Declare Function LoadLibrary Lib "kernel32" (ByVal lpFileName As String) As IntPtr`enter code here`
<DllImport("KERNEL32.DLL", EntryPoint:="FreeLibrary", SetLastError:=True)> _
Public Shared Function FreeLibrary(ByVal hModule As IntPtr) As Boolean
' Leave function empty - DLLImport attribute
' forces calls to LoadLibrary to
' be forwarded to LoadLibrary in KERNEL32.DLL
End Function
Public Const MAX_PATH As Integer = 256
' Dim testKernel As loadlibrary
Dim p As New Process
' Dim startInfo As New ProcessStartInfo("sysocmgr.exe", "/i:sysoc.inf /u:\"" + fileName + " \ "")
Dim fileName As String = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "MSMQAnswer.ans")
Dim writer As New StreamWriter(fileName)
' Override the 'Install' method of the Installer class. When overridden in a derived class, performs the installation.
'You must override the Install and Uninstall methods to add the code to perform your custom installation steps.
Public Overrides Sub Install(ByVal mySavedState As IDictionary)
MyBase.Install(mySavedState)
Dim loaded As Boolean = False
Dim fileName As String
Dim writer As StreamWriter
Dim p As Process
Try
Dim handle As IntPtr = LoadLibrary("Mqrt.dll")
If handle = IntPtr.Zero Or handle.ToInt32 = 0 Then
loaded = False
Else
loaded = True
FreeLibrary(handle)
End If
Catch ex As Exception
loaded = False
End Try
If Not loaded = True Then
If Environment.OSVersion.Version.Major < 6 Then ' windows xp or earlier
fileName = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "MSMQAnswer.ans")
writer = New System.IO.StreamWriter(fileName)
Using writer
writer.WriteLine("[Version]")
' writer.WriteLine("Signature = \"$Windows NT$\"")
writer.WriteLine("Signature = \""$Windows NT$\""")
writer.WriteLine()
writer.WriteLine("[Global]")
writer.WriteLine("FreshMode = Custom")
writer.WriteLine("MaintenanceMode = RemoveAll")
writer.WriteLine("UpgradeMode = UpgradeOnly")
writer.WriteLine()
writer.WriteLine("[Components]")
writer.WriteLine("msmq_Core = ON")
End Using
p = New System.Diagnostics.Process()
Using p
Dim startInfo As New ProcessStartInfo("sysocmgr.exe", "/i:sysoc.inf /u:\" + fileName + " \ ")
p.StartInfo = startInfo
p.Start()
p.WaitForExit()
End Using
Else 'windows vista or later, server 03
p = New System.Diagnostics.Process
Using p
Dim startInfo As New ProcessStartInfo("ocsetup.exe", "MSMQ-Container;MSMQ-Server /passive")
p.StartInfo = startInfo
p.Start()
p.WaitForExit()
End Using
End If
End If
End Sub
End Class

Related

AWS SDK .NET 4.5 "Error unmarshalling response back from AWS. HTTP Status Code: 200 OK" on ListObjectsV2

I am getting this error trying to list objects in a directory on a bucket. I cannot list from the root of the bucket as it has more than 1000 objects, so I need to drill farther down into the directory list to get what I want. My code works when I display from the root of the bucket, but when I try to add directories at the end of the bucket to list their contents I get this error. "Error unmarshalling response back from AWS. HTTP Status Code: 200 OK", "Root element is missing" on the ListObjectsV2. This is a public S3 bucket so I have included my code below so others can try it. I am using AWS-SDK-NET45.zip and compiling as Visual Basic 2019 for .NET 4.8 within an SSIS Script task. This should work, any ideas on what I am doing wrong? Thanks.
---CODE---
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports Amazon.S3
Imports Amazon.S3.Model
Imports Amazon.Runtime
Imports Amazon
Imports Amazon.S3.Util
Imports System.Collections.ObjectModel
Imports System.IO
'ScriptMain is the entry point class of the script. Do not change the name, attributes,
'or parent of this class.
<Microsoft.SqlServer.Dts.Tasks.ScriptTask.SSISScriptTaskEntryPointAttribute()>
<System.CLSCompliantAttribute(False)>
Partial Public Class ScriptMain
Inherits Microsoft.SqlServer.Dts.Tasks.ScriptTask.VSTARTScriptObjectModelBase
Public Sub Main()
'
' Add your code here
'
Dim filecol As ObservableCollection(Of String)
Try
'filecol = ListingFiles("/gov-fpac-rma-pubfs-production/pub/References/actuarial_data_master/2023/")
'filecol = ListingFiles("/gov-fpac-rma-pubfs-production/") 'Bucket root
filecol = ListingFiles("/gov-fpac-rma-pubfs-production/pub/")
Dts.TaskResult = ScriptResults.Success
Catch ex As Exception
Console.WriteLine(ex.Message.ToString)
Dts.TaskResult = ScriptResults.Failure
End Try
End Sub
#Region "ScriptResults declaration"
'This enum provides a convenient shorthand within the scope of this class for setting the
'result of the script.
'This code was generated automatically.
Enum ScriptResults
Success = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Success
Failure = Microsoft.SqlServer.Dts.Runtime.DTSExecResult.Failure
End Enum
#End Region
Private Function ListingFiles(bucketName As String, Optional foldername As String = "/") As ObservableCollection(Of String)
Dim obsv As New ObservableCollection(Of String)
Dim delimiter As String = "/"
Dim AWS_ACCESS_KEY As String = "xxxxxxxxxxxx" 'Add your Access Key here
Dim AWS_SECRET_KEY As String = "xxxxxxxxxxxxxxxxx" ' 'Add your Secret here
Dim s3config As AmazonS3Config = New AmazonS3Config
With s3config
.ForcePathStyle = True
.RegionEndpoint = RegionEndpoint.USEast1
End With
Dim s3Client As AmazonS3Client = New AmazonS3Client(AWS_ACCESS_KEY, AWS_SECRET_KEY, s3config)
If Not foldername.EndsWith(delimiter) Then
foldername = String.Format("{0}{1}", foldername, delimiter)
End If
Try
Try
Dim request As New ListObjectsV2Request()
With request
.BucketName = bucketName
End With
Do
Dim response As New ListObjectsV2Response()
response = s3Client.ListObjectsV2(request)
For i As Integer = 1 To response.S3Objects.Count - 1
Dim entry As S3Object = response.S3Objects(i)
If Not foldername = "/" Then
If entry.Key.ToString.StartsWith(foldername) Then
Dim replacementstring As String = Replace(entry.Key, foldername, "")
If Not replacementstring = "" Then
obsv.Add(replacementstring)
End If
End If
Else
obsv.Add(Replace(entry.Key, foldername, ""))
End If
MessageBox.Show(entry.Key + " " + entry.LastModified.ToString())
'Console.WriteLine("Object - " + entry.Key.ToString())
'Console.WriteLine(" Size - " + entry.Size.ToString())
'Console.WriteLine(" LastModified - " + entry.LastModified.ToString())
'Console.WriteLine(" Storage class - " + entry.StorageClass)
Next
If (response.IsTruncated) Then
request.ContinuationToken = response.NextContinuationToken
Else
request = Nothing
End If
Loop Until IsNothing(request)
Catch ex As AmazonS3Exception
Console.WriteLine(ex.Message.ToString)
Dts.TaskResult = ScriptResults.Failure
End Try
Catch ex As Exception
Console.WriteLine(ex.Message.ToString)
Dts.TaskResult = ScriptResults.Failure
End Try
Return obsv
End Function
End Class
Ok I added the prefix option to the ListObjectsV2Request as follows and it worked. I was able to get list of files from just the directory I wanted. I was side-tracked thinking it worked like the GetObjects function where you have to add the directory to the end of the bucketname and list the file you want in the Entry.Key. Hopefully others will find this of help since I did not find much for examples on this.
Dim request As New ListObjectsV2Request() 'With {.BucketName = bucketName}
With request
.BucketName = "/gov-fpac-rma-pubfs-production"
.Prefix = "pub/References/actuarial_data_master/2023/2023_"
End With

Mail merge with Libre Office using .net

I have following code block which is working perfectly for OpenOffice SDK to automate Mail merge functionality.
Public Function runQueryOnDataSource(ByVal nameOfdDtaource As String, ByVal query As String) As Boolean
strLog = strLog + vbCrLf + Now.ToString() + ": runQueryOnDataSource nameOfdDtaource:" + nameOfdDtaource + ",query:" + query + "-Started"
Dim oDB As Object, oBase As Object
Dim oStatement As Object
Dim rSQL As String
Dim oRequete As Object
Dim oServiceManager As Object, CreateUnoService As Object
Try
'Creation instance Open office
oServiceManager = CreateObject("com.sun.star.ServiceManager")
CreateUnoService = oServiceManager.createInstance("com.sun.star.sdb.DatabaseContext")
mxMSFactory = (uno.util.Bootstrap.bootstrap()).getServiceManager()
oDB = CreateUnoService.getByName(nameOfdDtaource) 'oDB=XDataSource
'Connection
oBase = oDB.getConnection("", "") 'oBase=XConnection
oStatement = oBase.createStatement 'XStatement
'rSQL = "SELECT * FROM ""26_MailMergeResult_DEMO"
rSQL = query
oRequete = oStatement.execute(rSQL)
Return True
Catch ex As Exception
strLog = strLog + vbCrLf + Now.ToString() + ": Exception" + ex.ToString()
Throw ex
Finally
oDB = Nothing
oBase.Close()
oBase.Dispose()
End Try
strLog = strLog + vbCrLf + Now.ToString() + ": runQueryOnDataSource-Finished"
Return True
End Function
Above code is used to insert data into the DataSource already registered with libre office.But Now when I try to use it, line oServiceManager = CreateObject("com.sun.star.ServiceManager") generates error "Error Creating ActiveX object".
Do anyone have idea, How do I fix this.
This code does not look right, so I'm surprised it ever worked. In other examples, the bootstrap() line always goes first. Then use that service manager instead of a separate oServiceManager variable.
For example, see the Java code at https://www.openoffice.org/udk/common/man/spec/transparentofficecomponents.html.
EDIT:
You're almost there. The getByName() method returns uno.Any, which has a property called Value that DirectCast can use.
Dim oDB As XDataSource
Dim oBase As XConnection = Nothing
Dim xContext As XComponentContext = uno.util.Bootstrap.bootstrap()
Dim xMSFactory As XMultiServiceFactory = DirectCast(
xContext.getServiceManager(), XMultiServiceFactory)
Dim xNameAccess As XNameAccess = DirectCast(
xMSFactory.createInstance("com.sun.star.sdb.DatabaseContext"), XNameAccess)
oDB = DirectCast(xNameAccess.getByName("Bibliography").Value, XDataSource)
oBase = DirectCast(oDB.getConnection("", ""), XConnection)

Backend sent unrecognized response type: u Error with Postgres 9.3 and npgsql

I upgraded my server yesterday from Postgres 9.1 to 9.3 and since then I've been getting an error: Backend sent unrecognized response type: u
I'm using npgsql to connect from my application to the server.
I remember that I used to get this error a while back and I haven't seen it in a while.
A full line from my log is:
Backend sent unrecognized response type: u
INSERT INTO stockcodes_rating (item_code,rating,price_range,user_id,timestamp_of_rating) VALUES ('10245684','5','Reasonable','10832',now())
My code for the procedure is:
Public Function InsertRating(ByVal Stockcode As String, ByVal Rating As Integer, ByVal PriceRange As String, ByVal UserId As String) As String
Dim objDBWrite As dlNpgSQL
objDBWrite = New dlNpgSQL("PostgreConnectionStringWrite", ConfigurationManager.AppSettings("CurrentDatabase"))
tmpSQL = "INSERT INTO stockcodes_rating (item_code,rating,price_range,user_id,timestamp_of_rating) VALUES " & _
"('" & Stockcode.ToUpper & "','" & Rating & "','" & PriceRange & "','" & UserId & "',now())"
Try
objDBWrite.ExecuteQuery(tmpSQL)
Catch ex As Exception
objDBWrite.CloseConnection()
Return ex.Message
Finally
objDBWrite.CloseConnection()
End Try
Return "Success"
End Function
My code for the dlNpgSQLclass is:
Imports Npgsql
Public Class dlNpgSQL
Dim _sqlConnection As NpgsqlConnection
Dim _sqlCommand As NpgsqlCommand
Dim _sqlDataAdapter As NpgsqlDataAdapter
Dim _dataset As DataSet
Public Sub New()
On Error GoTo ErrZ
_sqlConnection = New NpgsqlConnection(ConfigurationManager.ConnectionStrings("PostgreRemoteConnectionString").ConnectionString)
Exit Sub
End Sub
Public Sub New(ByVal WhichConnectionString As String)
On Error GoTo ErrZ
_sqlConnection = New NpgsqlConnection(ConfigurationManager.ConnectionStrings(WhichConnectionString).ConnectionString)
Exit Sub
End Sub
Public Sub New(ByVal WhichConnectionString As String, ByVal WhichDB As String)
On Error GoTo ErrZ
_sqlConnection = New NpgsqlConnection(ConfigurationManager.ConnectionStrings(WhichConnectionString).ConnectionString & "database=" & WhichDB & ";")
Exit Sub
End Sub
Public Function OpenConnection() As NpgsqlConnection
Try
If _sqlConnection.State = ConnectionState.Closed Then
_sqlConnection.Open()
End If
Catch ex As Exception
End Try
Return _sqlConnection
End Function
Public Sub CloseConnection()
Try
If _sqlConnection.State = ConnectionState.Open Then
_sqlConnection.Close()
End If
Catch ex As Exception
End Try
End Sub
Public Function GetDataSet(ByVal strQuery As String) As DataSet
'NpgsqlEventLog.Level = LogLevel.Normal
'NpgsqlEventLog.LogName = ("c:\npgsql.log")
'NpgsqlEventLog.EchoMessages = True
_dataset = New DataSet
Try
_sqlDataAdapter = New NpgsqlDataAdapter(strQuery, OpenConnection)
_sqlDataAdapter.Fill(_dataset)
Catch ex As Exception
End Try
Return _dataset
End Function
Public Function ReleaseDataSet(ByRef ds As DataSet) As Boolean
Try
ds.Clear()
ds.Dispose()
Catch ex As Exception
End Try
Return True
End Function
Public Function ExecuteQuery(ByVal strQuery As String) As String
'NpgsqlEventLog.Level = LogLevel.Normal
'NpgsqlEventLog.LogName = ("c:\npgsql.log")
'NpgsqlEventLog.EchoMessages = True
Dim RecordsReturned As String = ""
Try
_sqlCommand = New NpgsqlCommand(strQuery, OpenConnection)
RecordsReturned = _sqlCommand.ExecuteNonQuery()
Catch ex As Exception
Return ""
End Try
Return RecordsReturned
End Function
Public Function isR(ByVal tmpDs As DataSet, Optional ByVal tablename As Integer = 0) As Boolean
Try
If tmpDs.Tables.Count > 0 Then
If tmpDs.Tables(0).Rows.Count > 0 Then
isR = True
Else
isR = False
End If
End If
Catch ex As Exception
isR = False
End Try
End Function
End Class
What version of npgsql are you using? You probably need to upgrade to 2.0.14.3.
Better yet, try out the 2.1.0-beta1 which is quite stable and about to be released.
The same thing happened to me using Npgsql 2.0.12.0 sharing the connection between threads. Making a new connection in each thread was the solution!

How to generate word document in windows server 2003?

I had written a function to generate a word document by using the Office Interop Word object. My code is as shown below. It is working fine in my local system. But when i try to run it from window server 2003 it is not working. It keeps loading at Word.Document wordDoc = wordApp.Documents.Open and doesn't do anything. Could you help me out?
private void GenerateEmploymentCertificate()
{
object Nothing = System.Reflection.Missing.Value;
object format = Word.WdSaveFormat.wdFormatDocument;
Word.Application wordApp = new Word.ApplicationClass();
object srcFileName = Server.MapPath(ResolveUrl(#"~/HRLetter\Arabia\Templates\Employment Certificate.doc"));
Word.Document wordDoc = wordApp.Documents.Open
(ref srcFileName, ref format, ref Nothing, ref Nothing,
ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing,
ref Nothing, ref Nothing, ref Nothing, ref Nothing, ref Nothing,
ref Nothing, ref Nothing);
try
{
object bookmarkDate = "Date";
wordDoc.Bookmarks.get_Item(ref bookmarkDate).Select();
wordApp.Selection.Text = string.Format("{0:MM/dd/yyyy}", lblRequestdate.Text);
object bookmarkEmployeeName = "EmployeeName";
wordDoc.Bookmarks.get_Item(ref bookmarkEmployeeName).Select();
wordApp.Selection.Text = lblEmployeeName1.Text;
object bookmarkCompany = "Company";
wordDoc.Bookmarks.get_Item(ref bookmarkCompany).Select();
wordApp.Selection.Text = lblCompanyName1.Text;
object bookmarkJoiningDate = "JoiningDate";
wordDoc.Bookmarks.get_Item(ref bookmarkJoiningDate).Select();
wordApp.Selection.Text = string.Format("{0:MM/dd/yyyy}", lblJoiningDate1.Text);
object bookmarkDesignation = "Designation";
wordDoc.Bookmarks.get_Item(ref bookmarkDesignation).Select();
wordApp.Selection.Text = lblDesignation1.Text;
string DocName;
DocName = string.Format("{0}_employment_certificate", lblRequestNo.Text);
hFilename.Value = DocName;
wordDoc.SaveAs(Server.MapPath(ResolveUrl(#"~/HRLetter\Arabia\Letters\" + DocName + ".doc")));
}
catch (Exception exp)
{
Session["generalError"] = null;
Session["generalError"] = "There was an error at generating the letter. Please send email to unify.admin#unilever.com with this screen shot.<br /><br /><br />Request No:" + lblRequestNo.Text + "<br />Action:Submit<br />" + exp.StackTrace.ToString();
LogManager logHelper = new LogManager(Request.PhysicalApplicationPath.Trim(), "Leave System - Malaysia");
logHelper.LogError("[btnSubmit_Click - ]" + exp.Message + ".StackTrace - " + exp.StackTrace.ToString());
Response.Redirect(ResolveUrl("~/Error/ErrorHandler.aspx"));
}
finally
{
// Close wordDoc2
wordDoc.Close(ref Nothing, ref Nothing, ref Nothing);
if (wordDoc != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(wordDoc);
wordDoc = null;
}
// close wordApp
wordApp.Quit(ref Nothing, ref Nothing, ref Nothing);
if (wordApp != null)
{
System.Runtime.InteropServices.Marshal.ReleaseComObject(wordApp);
wordApp = null;
}
}
GC.Collect();}
MS office doesn't really work in server environment. Even MS says so.
We've made it work with LibreOffice. You can read it on our blog

SSIS Script transformation error using ADO.NET

I'm getting an error that states Incorrect syntax near ')'. when executing my SSIS package. The error is being thrown by a Script transformation component in the DFT. From what I can tell it is being thrown by the sqlReader = sqlCmd.ExecuteReader() line. I have been looking at it for days now and can't seem to figure out what is causing the error. I've included the contents of the script component below. Anyone have any ideas?
Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Pipeline.Wrapper
Imports Microsoft.SqlServer.Dts.Runtime.Wrapper
Imports System.Data.SqlClient
Public Class ScriptMain
Inherits UserComponent
Dim connMgr As IDTSConnectionManager90
Dim sqlConn As SqlConnection
Dim sqlCmd As SqlCommand
Dim sqlParam As SqlParameter
Public Overrides Sub AcquireConnections(ByVal Transaction As Object)
connMgr = Me.Connections.connTalisma
sqlConn = CType(connMgr.AcquireConnection(Nothing), SqlConnection)
End Sub
Public Overrides Sub PreExecute()
sqlCmd = New SqlCommand("SELECT Name FROM dbo.Category WHERE CatID = #catid)", sqlConn)
sqlParam = New SqlParameter("#catid", SqlDbType.Int)
sqlCmd.Parameters.Add(sqlParam)
End Sub
Public Overrides Sub ReleaseConnections()
connMgr.ReleaseConnection(sqlConn)
End Sub
Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
Dim sqlReader As SqlDataReader
Dim delimitedField As String = Row.FinalCallReason
Dim delimiter As String = ";"
Dim tempField As String
If Not (String.IsNullOrEmpty(delimitedField)) Then
Dim DelimitedListArray() As String = delimitedField.Split(New String() {delimiter}, StringSplitOptions.RemoveEmptyEntries)
For Each item As String In DelimitedListArray
sqlCmd.Parameters("#catid").Value = CInt(item)
MsgBox(item)
Try
sqlReader = sqlCmd.ExecuteReader()
tempField = tempField + ";" + sqlReader.GetString(0)
Catch e As Exception
MsgBox("Error: " + e.Message)
End Try
Next
End If
Row.FinalCallReason = tempField
End Sub
End Class
In the following section of the code, change #catid) to #catid in the SqlCommand object initialization statement.
Remove the parentheses. It is not needed. The parentheses is causing the query to fail and hence the error message Incorrect syntax near ')'.
Public Overrides Sub PreExecute()
sqlCmd = New SqlCommand("SELECT Name FROM dbo.Category WHERE CatID = #catid)", sqlConn)
sqlParam = New SqlParameter("#catid", SqlDbType.Int)
sqlCmd.Parameters.Add(sqlParam)
End Sub