How to Catch WMI Errors - exception

I want to use wmi to stop a service if it is running. Below is the code in vbscript.
The problem is, GetObject, startService, and ExecuteQuery commands may get errors because of various reasons. For example, after issuing "stopService" command, the state of the service may become "stopping", instead of "stopped", and the script is hanging there for quite some time. Sometimes, error messages such as "RPC is not available" was returned. Seems there is no catch exception machanism built into vbscript. Most of the examples I saw online never considered such situation. Does anybody know there is a good way to catch such kind of errors, and force these command (note: not service itself) to abort?
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colServiceList = objWMIService.ExecQuery ("Select * from Win32_Service where Name = '" & strService & "'")
For Each objService in colServiceList
If objService.State = "Running" Then
strObjService.StopService
Wscript.Sleep 2000
myColServiceList = myObjWMIService.ExecQuery _
("Select * from Win32_Service where Name = '" & strService & "'")
For each myObjService In myColServiceList
objState = myObjService.State
End If
End If
[/code]

You must read this article from Microsoft To Err Is VBScript in this link you will find everything which you must know about handle errors using the the WMI and VbScript.

Related

Setting Validation rules to multiple fields using VBA code returns error 3309 (too large)

I would like to ask you for help with (edited) VBA code I found while searching for solution. My goal is to add validation rule to multiple field of table at once by VBA code. I have to use VBA code because there is so many fields and manual input would be insane.
Validation rule: NOT LIKE "*"+Chr(10)+"*" OR "*"+Chr(13)+"*" OR "*"+Chr(9)+"*"
(user can't save "enter", "ctrl+enter" and "tabulator")
For using this rule in VBA function the syntax is quite different but input to MS Access is correct.
My VBA code (not directly my, I found it and edit to my needs)
Public Function SetFieldValidation()
Dim dbs As DAO.Database
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Dim strValidRule As String
Dim strValidText As String
Dim bytNumOfFields As Byte
strValidRule = "NOT LIKE " & Chr(34) & "*" & Chr(34) & "+Chr(10)+" & Chr(34) & "*" & Chr(34) & " OR " & Chr(34) & "*" & Chr(34) & "+Chr(13)+" & Chr(34) & "*" & Chr(34) & " OR " & Chr(34) & "*" & Chr(34) & "+Chr(9)+" & Chr(34) & "*" & Chr(34)
strValidText = "Some error msg"
Set dbs = CurrentDb
Set tdf = dbs.TableDefs("Table_Name")
For bytNumOfFields = 0 To tdf.Fields.Count - 1
With tdf.Fields(bytNumOfFields)
If .Name <> "Record ID" Then
.ValidationRule = strValidRule
.ValidationText = strValidText
End If
End With
Next
End Function
In the past this script works with rule NOT LIKE "*"+Chr(10)+"*" OR "*"+Chr(13)+"*".
Than tried to add OR "*"+Chr(9)+"*".
Since this modification the MS Access (VBA) returns error: Property value is too large. (Error 3309) while I run the script. When I tried return to previous version of script without +Chr(9)+, the error still remains (even I succesfully used this script in the past and validation rules are set in another tables).
I'm really beginer in VBA, honestly I only need to setup this rule to all field of all tables. Can someone experienced tell me what's wrong in the code?
Thank you very much.
I suggest not using Chr(). Since Chr will always return the same value for a particular number, e.g. Chr(65) always returns A, I don't think you need to use the function to get the value you want. So try setting your strValidRule as one long static string with the characters returned by the Chr() functions hard coded.
I did a research and probably the problem is somewhere else - looks like error in table design of specific table.
1.) First test: At first I tried to debug strValidRule string and compare two approaches for string (my and with quotes as #Rominus advised). The results are same but quoString is smoother approach. Than I run script (tried both approaches). Error msg said 'Property Value Too Large' error 3309 and the old valid rules remains in table design unchanged (rules were set in the past and remains).
Sub teststring()
chrString = "chrString: NOT LIKE " & Chr(34) & "*" & Chr(34) & " +Chr(10)+ " & Chr(34) & "*" & Chr(34) & " OR " & Chr(34) & "*" & Chr(34) & " +Chr(13)+ " & Chr(34) & "*" & Chr(34)
Debug.Print chrString
quoString = "quoString: NOT LIKE ""*"" +Chr(10)+ ""*"" OR ""*"" +Chr(13)+ ""*"""
Debug.Print quoString
End Sub
2.) Second test: From my script above I firstly 'commented' values of strValidRule and strValidText by ' and add empty values "". Script run without error msg and added empty values.
Than I 'uncommented' the values and run script with values mentioned above (quoString approach and some msg for strValidText). Scritp run with error msg 'Property Value Too Large' error 3309. BUT, when I checked table design, the valid rules were properly set and working even the error msg popped up.
3.) Third test: I tried to use script in another table and run it without previously adding empty values described in step 2. (because in table were set old valid rules too). Script successfully overwrote old valid rules by new ones without msg of error 3309.
So, I found the way how to set valid rules but there is still some bug that shows error msg in specific table. Don't know how to fix it but I hope it haven't affect of my main goal (setting new working valid rules).

How to view what is inside the parameter when using MySqlCommand..Parameters.Add(New MySqlParameter("#sampleVariable", sampleVariable))

For example I have this query
MySQL_Query = "UPDATE `owner_info` " _
& "SET isArchived = 1 " _
& "WHERE id=#ownerID"
Dim MySQL_CMD As New MySqlCommand(MySQL_Query, MysqlConn)
Try
MySQL_CMD.Connection.Open()
MySQL_CMD.CommandText = MySQL_Query
MySQL_CMD.Parameters.Add(New MySqlParameter("#ownerID", ownerID))
MySQL_CMD.ExecuteNonQuery()
Catch myerror As MySqlException
Console.WriteLine("Error: Owner Info Delete")
Console.WriteLine(myerror)
Finally
MysqlConn.Close()
MysqlConn.Dispose()
End Try
If I use
console.writeline("Query: " & MySQL_Query")
It will output
UPDATE `owner_info` SET isArchived = 1 WHERE id=#ownerID
Is there a way that I can view what's inside the #ownerID?
Yeah I can do something like the below code, but it seems hassle?
console.writeline("Query: " & MySQL_Query" & "(" & ownerID & ")")
Is there any other way to do this? Maybe a more simple way.
The whole point of query parameters is that parameter data values are never substituted into the sql command text, even by the database server. In this way, any possibility of an injection vulnerability is eliminated. Thus, there is nothing built in to provide a populated or annotated command text, lest some naive programmer mistakenly use it to construct vulnerable queries.
However, you could easily build a re-usable method:
Function PrintQuery(ByVal cmd As IDbCommand) As String
Dim result As New StringBuilder(cmd.CommandText)
result.Append(vbCrLf & vbCrLf & "--Parameter List: ")
For Each p As DbParameter In cmd.Parameters
result.AppendFormat("{0}--({1} —— {2})", vbCrLf, p.ParameterName, p.Value)
Next p
Return result.ToString()
End Function

MS Access to MySQL Connection

I am building an application, using MS Access as a front-end of a MySQL DB. The application consists of a lot of Forms all of which will execute many different SQL statements.
I am establishing the connection using:
Dim oConn As New ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim User_ID As String
Dim Password As String
Server_Name = "localhost"
Database_Name = "test"
User_ID = "root"
Password = ""
oConn.Open "DRIVER={MySQL ODBC 5.3 ANSI Driver}" _
& ";SERVER=" & Server_Name _
& ";DATABASE=" & Database_Name _
& ";UID=" & User_ID _
& ";PWD=" & Password _
& ";OPTION=16427"
My questions are:
Is it better to Open and Close the connection each time i run an SQL Statement, or Open the connection, when the Application runs and close when the application closes?
-If the first way is better, Can I Create a global Function that returns a connection, to be used in the current form and not having to write the same code over and over for each form and/or SQL statement?
-If the second way is better, Can I Declare and Open the Connection globally, so It can be used from any form?
Keep in mind that:
-There are 50+ different forms and sub-forms in the application.
-The application should be able to run on multiple computers at once accessing 1 database.
I had this same question and nobody got around to answering it.
In general, its better to keep the connection open when you're going to use it and close it when you're done, but not before then. Which is fine if you use it on a per-form basis but if it gets shared it gets a little more complicated.
What I did initially was open the connection for each form, subforms grabbed the connection from their parent, and the form closes the connection when it gets closed.
The issue, if multiple forms use the same connection, is that if you close that connection, other forms using it will have errors and fail. So, if you want to share the connection between forms you can, but just make sure that it never closes unless the file is being closed. I am currently using this method, since I have a base 'menu' form that can't be closed without closing the file, I close the connection onClose for that form.
Another thing to keep in mind, is that the computer could be randomly disconnected from the server, so any code that requires the connection should have a quick test to re-open the connection if it got closed by accident somehow.
EDIT:
In it's own module.
Public DB_CONNECTION As ADODB.Connection
Function openConnect(ByRef myconn As ADODB.Connection) As Integer
Static retries As Integer
Dim server As String
server = "localhost"
On Error GoTo connectError
myconn.ConnectionTimeout = 10
myconn.Open "DRIVER={MySQL ODBC 5.1 Driver};SERVER=" & server & "DATABASE=data;USER=" & getSQLuser & ";PASSWORD=password;Option=3"
openConnect = 1
retries = 0
Exit Function
connectError:
'retry several times on failure
Dim errADO As ADODB.Error
For Each errADO In myconn.Errors
Debug.Print vbTab & "Error Number: " & errADO.Number
Debug.Print vbTab & "Error Description: " & errADO.Description
Debug.Print vbTab & "Jet Error Number: " & errADO.SQLState
Debug.Print vbTab & "Native Error Number: " & errADO.NativeError
Debug.Print vbTab & "Source: " & errADO.Source
Debug.Print vbTab & "Help Context: " & errADO.HelpContext
Debug.Print vbTab & "Help File: " & errADO.HelpFile
If errADO.Number = -2147467259 Then
If retries < 3 Then
If MsgBox("Connection Error, Try to reconnect or close any connection-enabled forms,check your internet connection and try again.", vbCritical + vbRetryCancel, "Connection Error") = vbRetry Then
retries = retries + 1
Call openConnect(myconn)
Exit Function
End If
Else
MsgBox "Connection error. Retried 3 times, check your internet connection and/or contact your system administrator.", vbCritical + vbOKOnly, "Critical Connection Error"
retries = 0
Exit Function
End If
End If
Next
Select Case err
Case 0
Case Else
MsgBox "Error Code " & err & ", " & Error(err), vbCritical, "Error #" & err
End Select
openConnect = -1
End Function
Function closeConnect()
If Not (DB_CONNECTION Is Nothing) Then
If DB_CONNECTION.State = adStateOpen Then
DB_CONNECTION.Close
End If
End If
End Function
Function tryConnect()
Dim err
If DB_CONNECTION Is Nothing Then
Set DB_CONNECTION = New ADODB.Connection
Call openConnect(DB_CONNECTION)
Else
If Not (DB_CONNECTION.State = adStateOpen) Then
Call openConnect(DB_CONNECTION)
End If
End If
End Function
In my case, I never call openConnect directly, but always call tryConnect onOpen of any forms that use the DB, or before calls that might happen after some time (for example, the save button). If it's already open, no harm done, but if it's not it prevents an error.
closeConnect I call OnError and OnClose of the menu form.

Varying results when trying to handle errors in database login form

I am making a application which will verify a login to a MySQL Server, which is being done with an ADODB.Connection, then open up another HTA if no errors are given. I am trying to achieve this using nothing but HTA, VBScript and hard work … Without going into too much detail, I would like to catch an error message which will come up if the user puts in the wrong username/password.
Normally, if you do put in the wrong password or username, it comes up with a HTML Error message, which doesn't look very user friendly. That's what this code is trying to catch and make more friendly. Code segment below:
Sub MainLogin_click
dim strError
Uname = usertext.Value
Pword = passtext.Value
cstring = "DRIVER={MySQL ODBC 5.2w Driver};SERVER=Localhost;UID=" & Uname _
& ";PWD=" & Pword & ";DATABASE=maindb;"
conn = CreateObject("ADODB.Connection")
On Error Resume Next
conn.Open cstring
Call MakeDSN
If Err.Number <> 0 Then
strError = "LongBow Error" & VbCrLf & " Error Number: " & Err.Number _
& VbCrLf & " Error Source: " & Err.Source _
& VbCrLf & " Error Description: " & Err.Description
MsgBox(strError)
Err.Clear
Else
Set objShell = CreateObject("WScript.Shell")
objShell.Run("bin\LongBowAgent.hta")
Window.close
conn.Close
End If
On Error GoTo 0
End Sub
Basically when I run this code, and my HTA as a whole, either
Nothing happens, no activity when the 'login' button is pressed.
or
I get a nice error box (even with the right username/password) saying
Error 424, VBScript runtime error, object Required.
Honestly - I've been at this for 2 days now and tried many things. None have really worked, but then Google Searching can only do so much.
Any Help, and any advise would be great. I do not mind trying something completely different here, so long as it stays within HTA & VBScript.
The scope of your OERN is to large - it does not only hide errors of the .Open, but also problems in MakeDSN and in the error handling code.
Ironically, the first culprit is not covered by the OERN:
conn = CreateObject("ADODB.Connection")
is wrong, because you assign an object. Try
Set conn = CreateObject("ADODB.Connection")

Sending Email with Late Binding Error Through VBA

I'm trying to use a late binding to email from VBA in Access 2010 and Access 2003. 2003 gives me 'Could not complete the operation. Once or more paramet values are not valid.' and 2010 gives me 'Invalid procedure call or argument.' I've done the step through and it fails at .send near the bottom. Am I setting up my binding wrong? I'm trying to do this without using Microsoft Object Library in the References.
Thanks.
'Refers to Outlook's Application object
Dim appOutlook As Object
'Refers to an Outlook email message
Dim appOutlookMsg As Object
'Refers to an Outlook email recipient
Dim appOutlookRec As Object
'Create an Outlook session in the background
Set appOutlook = CreateObject("Outlook.Application")
'Create a new empty email message
Set appOutlookMsg = appOutlook.CreateItem(olMailItem)
'Using the new, empty message...
With appOutlookMsg
strSQL = "SELECT Email FROM Employees WHERE " & sqlVar & " = True"
Set myR = CurrentDb.OpenRecordset(strSQL)
Do While Not myR.EOF
Set appOutlookRec = .Recipients.Add(myR!Email)
appOutlookRec.Type = olTo
myR.MoveNext
Loop
strSQL = "SELECT Email FROM Employees WHERE '" & user & "' = Username"
Set myR = CurrentDb.OpenRecordset(strSQL)
Set appOutlookRec = .Recipients.Add(myR!Email)
appOutlookRec.Type = olCC
.Subject = wonum
.Body = "Department: " & strDep & vbNewLine & vbNewLine & _
"Issue is at: " & strIssue & vbNewLine & vbNewLine & _
"Priority is: " & strPriority & vbNewLine & vbNewLine & _
"Complete by: " & strDate & vbNewLine & vbNewLine & _
"Description: " & strDesc
.Send
End With
Without a reference, VBA will not know about Outlook constants such as olTo and olCC. With late binding (no reference), you must supply the values for constants rather than the names of the constants.
However, since you didn't report a compile error about those constants, that suggests your code module does not include Option Explicit in its Declarations section. Trying to troubleshoot VBA code without Option Explicit is a waste of time.
Add Option Explicit, then choose Debug->Compile from the VB Editor's main menu and fix anything the compiler complains about. Resume you troubleshooting afterward.
There is an article here on sending email via Outlook using early and late binding. In the "Late Bound Conversion Checklist" at the end, the last suggestion is
Add optional arguments that have a default value
I cannot vouch for that advice because when I need to send email messages from Access I use CDO, not Outlook. Still, it sounds like it might be worth a try.