Showing posts with label app. Show all posts
Showing posts with label app. Show all posts

Tuesday, March 27, 2012

Getting "is not static" when trying to deploy

I'm attemping to deploy a crypto class that we use on a desktop app to SQL Server. I'll use the encryptstring/decryptstring found in this class as User Defined Functions on SQL Server. When I try to deploy the class I'm getting this error:

Error 1 Method, property or field 'EncryptString' of class 'EncryptingDecryptingOASISPWDS.Crypto' in assembly 'EncryptingDecryptingOASISPWDS' is not static. EncryptingDecryptingOASISPWDS

Here is the code:

Imports System

Imports System.Data

Imports System.Data.SqlClient

Imports System.Data.SqlTypes

Imports Microsoft.SqlServer.Server

Imports System.Security.Cryptography

Imports System.Text 'for UnicodeEncoding

Imports System.IO 'for MemoryStream, FileStream, Stream, Path

Imports System.Threading 'for Thread.Sleep

Partial Public Class Crypto

'Private Const CodeVersion As String = "01.00.00"

'class member variables

Private m_sPassPhrase As String

'class private variables

Private mbytKey() As Byte 'crypto key

Private mbytIV() As Byte 'Initialization Vector

Private mbKeyIsSet As Boolean = False

Private mksKeyNotSetException As String = "Crypto passphrase is not set."

Private mksPassphraseTooSmall As String = "PassPhrase length must be at least {0} characters."

' class constructors

Public Sub New()

'no passphrase is useful for GetHashString/ValidPassword methods

End Sub

Public Sub New(ByVal CryptoPassPhrase As String)

PassPhrase = CryptoPassPhrase

End Sub

' class public properties

'generate and store encryption key & iv from passphrase

Public Property PassPhrase() As String

Get

Return m_sPassPhrase

End Get

Set(ByVal Value As String)

Const iMinLength As Integer = -1 '-1 disables min length

m_sPassPhrase = Value.Trim

'enforce a rule on minimum length if desired here

If (Value.Length > iMinLength) Or (iMinLength = -1) Then

Dim sha2 As New SHA256Managed()

'256 bits = 32 byte key

mbytKey = sha2.ComputeHash(BytesFromString(m_sPassPhrase))

'convert to Base64 for Initialization Vector, take last 16 chars

Dim sKey As String = Convert.ToBase64String(mbytKey)

mbytIV = Encoding.ASCII.GetBytes(sKey.Remove(0, sKey.Length - 16))

mbKeyIsSet = True

sha2 = Nothing

Else

mbKeyIsSet = False

Throw New Exception(String.Format(mksPassphraseTooSmall, (iMinLength + 1).ToString))

End If

End Set

End Property

'decrypt a stream

Public Function DecryptStream(ByVal EncryptedStream As MemoryStream) As MemoryStream

If mbKeyIsSet Then

Try

'create Crypto Service Provider, set key, transform and crypto stream

Dim oCSP As New RijndaelManaged()

oCSP.Key = mbytKey

oCSP.IV = mbytIV

Dim ct As ICryptoTransform = oCSP.CreateDecryptor()

Dim cs As CryptoStream = New CryptoStream(EncryptedStream, ct, CryptoStreamMode.Read)

'get bytes from encrypted stream

Dim byteArray(EncryptedStream.Length - 1) As Byte

Dim iBytesIn As Integer = cs.Read(byteArray, 0, EncryptedStream.Length)

cs.Close()

'create and write the decrypted output stream

Dim plainStream As New MemoryStream()

plainStream.Write(byteArray, 0, iBytesIn)

Return plainStream

Catch ex As Exception

Return Stream.Null

End Try

Else

Throw New Exception(mksKeyNotSetException)

End If

End Function

'decrypt a string - wrapper without Base64 flag (True by default)

Public Function DecryptString(ByVal EncryptedString As String) As String

Return _DecryptString(EncryptedString, True)

End Function

'decrypt a string - wrapper with Base64 flag

Public Function DecryptString(ByVal EncryptedString As String, ByVal Base64 As Boolean) As String

Return _DecryptString(EncryptedString, Base64)

End Function

'encrypt a stream

Public Function EncryptStream(ByVal PlainStream As MemoryStream) As MemoryStream

Try

'open stream for encrypted data

Dim encStream As New MemoryStream()

'create Crypto Service Provider, set key, transform and crypto stream

Dim oCSP As New RijndaelManaged()

oCSP.Key = mbytKey

oCSP.IV = mbytIV

Dim ct As ICryptoTransform = oCSP.CreateEncryptor()

Dim cs As CryptoStream = New CryptoStream(encStream, ct, CryptoStreamMode.Write)

'get input stream into byte array

Dim byteArray() As Byte = PlainStream.ToArray()

'write input bytes to crypto stream and close up

cs.Write(byteArray, 0, PlainStream.Length)

cs.FlushFinalBlock()

cs.Close()

Return encStream

Catch ex As Exception

Return Stream.Null

End Try

End Function

'encrypt a string - wrapper without Base64 flag (True by default)

<Microsoft.SqlServer.Server.SqlFunction()> _

Function EncryptString(ByVal PlainText As String) As String

Return _EncryptString(PlainText, True)

End Function

''encrypt a string - wrapper with Base64 flag

<Microsoft.SqlServer.Server.SqlFunction()> _

Public Function EncryptString2(ByVal PlainText As String, ByVal Base64 As Boolean) As String

Return _EncryptString(PlainText, Base64)

End Function

'calculates the hash of InputValue, returns a string

'- SHA1 hash is always 20 bytes (160 bits)

Public Function GetHashString(ByVal InputValue As String) As String

Try

Dim inputBytes() As Byte = BytesFromString(InputValue)

Dim hashValue() As Byte = New SHA1Managed().ComputeHash(inputBytes)

Return BytesToHexString(hashValue)

Catch ex As Exception

Return String.Empty

End Try

End Function

'returns True if hash of Passphrase matches HashValue

Public Function ValidPassword(ByVal Passphrase As String, ByVal HashValue As String) As Boolean

Return (GetHashString(Passphrase) = HashValue)

End Function

'internal string decryption

Private Function _DecryptString(ByVal EncryptedString As String, ByVal Base64 As Boolean) As String

Try

'put string in byte array depending on Base64 flag

Dim byteArray() As Byte

If Base64 Then

byteArray = Convert.FromBase64String(EncryptedString)

Else

byteArray = BytesFromString(EncryptedString)

End If

'create the streams, decrypt and return a string

Dim msEnc As New MemoryStream(byteArray)

Dim msPlain As MemoryStream = DecryptStream(msEnc)

Return BytesToString(msPlain.GetBuffer)

Catch ex As Exception

Return String.Empty

End Try

End Function

'internal string encryption

Private Function _EncryptString(ByVal PlainText As String, ByVal Base64 As Boolean) As String

Try

'put string in byte array

Dim byteArray() As Byte = BytesFromString(PlainText)

'create streams and encrypt

Dim msPlain As New MemoryStream(byteArray)

Dim msEnc As MemoryStream = EncryptStream(msPlain)

'return string depending on Base64 flag

If Base64 Then

Return Convert.ToBase64String(msEnc.ToArray)

Else

Return BytesToString(msEnc.ToArray)

End If

Catch ex As Exception

Return String.Empty

End Try

End Function

'returns a Unicode byte array from a string

Private Function BytesFromString(ByVal StringValue As String) As Byte()

Return (New UnicodeEncoding()).GetBytes(StringValue)

End Function

'returns a hex string from a byte array

Private Function BytesToHexString(ByVal byteArray() As Byte) As String

Dim sb As New StringBuilder(40)

Dim bValue As Byte

For Each bValue In byteArray

sb.AppendFormat(bValue.ToString("x2").ToUpper)

Next

Return sb.ToString

End Function

'returns a Unicode string from a byte array

Private Function BytesToString(ByVal byteArray() As Byte) As String

Return (New UnicodeEncoding()).GetString(byteArray)

End Function

'Return True when the file is available for writing

'- returns False if output file locked, for example

Private Function CheckWriteAccess(ByVal FileName As String) As Boolean

'2 second delay with 10,200

Dim iCount As Integer = 0 'retry count

Const iLimit As Integer = 10 'retries

Const iDelay As Integer = 200 'msec

While (iCount < iLimit)

Try

Dim fs As FileStream

fs = New FileStream(FileName, FileMode.Append, _

FileAccess.Write, FileShare.None)

fs.Close()

Return True

Catch ex As Exception

Thread.Sleep(iDelay)

Finally

iCount += 1

End Try

End While

Return False

End Function

End Class

All CLR functions / SP used by SQL Server are required to be Static since sql server cannot instantiate a class before using it... it uses only static methods that does not requires any instance.

So you must declare

<Microsoft.SqlServer.Server.SqlFunction()> _

Static Function EncryptString(ByVal PlainText As String) As String

...


Monday, March 26, 2012

Getting "When connecting to SQL Server 2005 Error" using MS SQL 2000?

I'm new to using VS2005 and this is my first project connecting to our MS SQL 2000. App worked fine on my dev PC, connection to the same MS SQL Server. Published the web site to the web server (same server running MS SQL Server) and getting the below error. Is this a permission setup problem on SQL Server or does it really think it's connecting with a MS SQL 2005 database?

An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)

Description:An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details:System.Data.SqlClient.SqlException: An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)

Where is your published website hosted? I would suggest you check the connection strings in your web.config file. It might be the case that when you were developing, the server was (local) but now since you published the website to another server, it is still trying to connect to the (local) server where it should connect to the remote server.

|||

Thanks for the reply. I attached my connection string info from the web.config file and you can see it's pointing to Server8.

The web site is published on Server8 also. Server8 is our Windows 2003 server running IIS and SQL Server 2000. So while in dev mode on my local PC, I was hitting server8 it appears.

<connectionStrings>

<addname="PP_PlusDevConnectionString"connectionString="Data Source=server8;Initial Catalog=PP_PlusDev;Integrated Security=True"

providerName="System.Data.SqlClient" />

<addname="PP_PlusDevConnectionString2"connectionString="Data Source=server8;Initial Catalog=PP_PlusDev;Integrated Security=True"

providerName="System.Data.SqlClient" />

</connectionStrings>

|||

Whoa, it just occurred to me what the problem could be, but I still need help on resolving it. I recently installed the SharePoint Service 3.0 on Server8, and found out the hard way I didn't install it correctly. I was hoping it would use the existing MS SQL 2000, but instead it installed the MS SQL 2005 express. I also had to change the Port for my IIS Intranet site to use port 8081, as Sharepoint comandeered port 80.

So, I have to wonder, how does the connection string on my Dev PC know to hit the MS SQL 2000 database, but the same web site published on server8 appears to be hitting the MS SQL 2005 express? I guess I will be researching this with Sharepoint in mind. Any ideas?

|||

Since SQL Server 2000, you can have multiple instances of SQL Server installed on a single machine. You can have up to onedefault instance,and then multiplenamed instances. The limit on the number of named instances depends on the edition of SQL Server you have installed.

I'd guess that the SQL Server 2000 is the default instance. By default, SQL Express is installed to the named instance .\SQLEXPRESS, but you can change that at installation. (The . just means local machine; you can substitute the machine name or localhost).

You can specify the instance as part of the connection string, such as Server8 or Server8\SQLEXPRESS.

But I'm betting this is not your problem. By default, when you install any version of SQL Server 2005, it does not allow remote connections, just as the error message said. You have to manually enable this, either through the Surface Area Configuration Tool or with T-SQL.

But the question remains: Is Server8 also your Web server? If it is, then you are not connecting remotely. In that case the problem lies elsewhere.

I hope this helps you find the problem, rather than making it more confusing!

Don

|||

I think it's the other way around. I think it's defaulting to SQL Server Express and I want it to default to SQL Server 2000. Is there something I can do to insure this?

But to answer your question, Server8 is indeed the Web server and running SQL Server 2000 and SQL Server Express.

|||

Okay, then try this. In your connection string, make the Data Source parameter localhost instead of server8. ADO.NET may be getting confused thinking that it is accessing a remote server. If that solves the problem, great.

But it still confuses me that you seem to be defaulting to SQL Express. That suggests that Express was installed as the default instance and that SQL Server 2000 was installed as a named instance. Is there any way to can find out what instances of SQL SErver are installed and their names? Maybe with Server Explorer in Visual Studio? Or you may have to ask the hosting company.

But it still feels like we're missing something...

Don

|||

I think you are on the right path. I changed Server8 to localhost in the web.config and did get a differnt error which led me to check out the ASP.net configuration for the Intranet web site. I wanted to confirm that it was indeed using ASP.net v2, as v1 appears to be getting set by default. It was set to v2, but I saw the option to edit the web.config. Clicked on that option and found the following setting:

LocalSQLServer - data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true

I think this qualifies as the AH-ha moment. So now, what should I set this too to look at the MS SQL 2000? I think you have already answered that, so let me confirmed the named instance of it...right?

|||

I did confirm the named instance is: MSSQLSERVER

So replaced SQLEXPRESS with MSSQLSERVER.

Now getting the follower error:Login failed for user 'NT AUTHORITY\NETWORK SERVICE'

1. I suspect I didn't update the web config correctly, as it should be using integrated security.

2. When I get back to VS and edit the remote project, it tells me the web.config has been edited by another source, do I want to set it back to default. I would rather set this correctly in VS, but I don't see in the web config where the server named instance is set.

|||

I think your first connection string was fine to connect to sql server 2000. Because to connect to SQL Server 2005 you have to provide "data source=.\SQLEXPRESS" if you have used the default instanse name while installing SQL Server 2005.

Now I would suggest you to use the first connection string and also do some configurations on you server. Go to stat-->programs--> Sql Server 2000-->client Network Utility. Select General Tab and make sure that "TCP/IP" and "Named Pipes" protocols are enabled. Hope it will solve your problem.

|||

Thanks for all the replies...but now I'm getting confused. TCPIP and Named Pipes have been enabled all along, no change has been made there.

Keep in mind I installed MS SQL Server 2000 first. Just recently I installed the SharePoint Service 3.0 that installed SQLExpress, which is only used by Sharepoint. I want my ASP.net applications to use MS SQL Server. I do NOT want to connect to SQL Server 2005 Express.

The named instance for SQL Server 2000 is MSSQLSERVER

But just changing the named instance in the web.config was not enough. I suspect I need the correct connection string which I do not have. Here's what I currently have it set to via IIS ASP.net edit web config: data source=.\MSSQLSERVER;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true

But to add to my confusion, I do not see this reflected in the Web.config when viewed via VS 2005.

I'll be happy to use the orignal connection string, but maybe I'm missing your point as I don't see how.

|||

thirt:

Here's what I currently have it set to via IIS ASP.net edit web config: data source=.\MSSQLSERVER;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true

Your connection string needs changing, since it is set up for SQL Express. It should look something like this:

data source=.\MSSQLSERVER;Integrated Security=SSPI;Initial Catalog=PP_PlusDev

That is more like what you started with, but now you have the data source set correctly.

Don

|||

Thanks! I used that string but back to getting this error:Login failed for user 'NT AUTHORITY\NETWORK SERVICE'.

I looked to add this into the SQL's security but couldn't find that name or service.

|||

Okay, cool. It's always progress when the error message changes!

This means that the NETWORK SERVICE, the default process identity for ASP.NET, doesn't have permissions to access SQL Server. You can resolve this in two ways. One way is to give NETWORK SERVICE the permissions it needs in the database, such as to access specific stored procedures or tables used by your application. The other is to instead use a SQL Server login, which you have to specify in your connection string. That login would have the permissions necessary for your application.

Does this make sense?

Don

|||

>>One way is to give NETWORK SERVICE the permissions it needs in the database

I'm having problems finding this service. I go to EM's Security/logins/add new user/select the local server/and can't find the NT or Network Service to add.

GetReportParameters ignores language="en-gb"?

Hello

I've integrated my reports into an app using the ReportViewer control, and I've created custom parameter selection controls. I want the user to be able to enter dates in dd/mm/yy format into a textbox. I've set the language of my reports to en-gb.

The SetParametes method of the ReportViewer control copes with this fine, but when I pass a date string in dd/mm/yy format into GetReportParameters, I get a 'parameter value not valid for its type' error. But it works for date strings in mm/dd/yy format, so it's as if GetReportParameters is ignoring my language setting.

Has anyone got any idea as to where I'm going wrong?

Thanks in advance

Dominic

After a little more playing around with this I've found that, on my machine, the SetParameters method always wants dates in dd/mm/yy format, whilst the GetReportParameters web method of the Report Service always wants dates in mm/dd/yy format, regardless of what I set the language of the report to.

Does anyone know what's going on?