How let Access release the ODBC - vba

I have 2 access databases, one in use as CRM and the other only holds linked tables to a firebird database using ODBC. This firebird database (fdb) is only capable to allow access to one user.
When updating the tables by the CRM through ODBC, the ODBC connection (Firebird) is not released, which means that an other application which needs access cannot open the database. The ODBC connection is only released when the CRM is closed.
Dim dba as database
Dim strODBCname as string
strODBCname = "OSF_ODBC.accdb"
Set dbs = OpenDatabase(ValidatePath(CurrentProject.Path, False) & strODBCname)
dbs.execute .... (etc.)
And after all record R/W are completed
set dbs = nothing
Is there an other way to enforce the release of the ODBC connection?
Peter

I've currently no idea how to explicitely release the ODBC connections of the current session, but you could open the database in a second Access application session (a second MsAccess.exe in memory) and release this after work:
Const ODBC_NAME As String = "OSF_ODBC.accdb"
With CreateObject("Access.Application")
.OpenCurrentDatabase ValidatePath(CurrentProject.Path, False) & ODBC_NAME
.CurrentDb.Execute ...
.CurrentDb.Close
.Quit
End With
This should release the connections for sure.

I don't know which version of Access you are using. But before you create a new application object, you should try
Set wrkAcc = CreateWorkspace("", "admin", "", dbUseJet)
Set dbs = wrkAcc.OpenDatabase(ValidatePath(CurrentProject.Path, False) & strODBCname)
or the next level up:
dim dbe=dao.dbengine
set dbe=CreateObject("dao.dbengine")
Set dbs= dbe.OpenDatabase(ValidatePath(CurrentProject.Path, False) & strODBCname)
More globally, you can modify the registry settings that control ODBC connection caching.

Related

calling a uid and pwd file into an access db for a system dsn

I have 5 different MS Access 2013 db files which connect to system dsn files(Linked Server)
The machine/system dsn's are Oracle based but the issue I am running into is 1 my password isn't encryped and has to be changed every 90 days and
2 I have to open each file and save my password multiple times when its changed.
I want to have a secure location which has the credentials stored and pass this into access so that they are not visible to other users and
not having to save my password on each access file and relink it.
I have googled for over 2 days but can't find anything other than looking at connection strings which still doesn't solve the problem. What do I need to look at to solve this?
Sorry I dont have code as I just use the linked tables wizard inside of ms access.
#Albert D I couldn't get your code to work but I have done the following which fixes the issue on the tables but not the Pass Through queries
Created a File DSN and linked some tables to the access database.
Created an Excel File to store my UserName And Passwords but my credentials in the pass-through query still show which I am stuck on?
Option Compare Database
Function Connections()
On Error Resume Next
'delete query if exists
DoCmd.DeleteObject acQuery, "PTQ"
Err.Clear
On Error GoTo 0 '"on error" statement here
'GET EXCEL LOGIN DETAILS
Set xlsApp = CreateObject("Excel.Application")
Dim WkBk As Excel.WorkBook
Set WkBk = xlsApp.WorkBooks.Open(FileName:="C:\folderlocation\filename.xlsx")
Dim USERLIST As String
Dim PWDLIST As String
USERLIST = WkBk.Sheets(1).Range("A2").Value
PWDLIST = WkBk.Sheets(1).Range("B2").Value
If Not (xlsApp Is Nothing) Then xlsApp.Quit
'end excel stuff
Dim db As DAO.Database
Dim qdExtData As QueryDef
Dim strSQL As String
Set db = CurrentDb
'passthrough query statement
strSQL = "SELECT * FROM table"
Set qdExtData = db.CreateQueryDef("PTQ")
ServerName = "Server1"
qdExtData.Connect = "ODBC;DRIVER={Oracle in OraClient11g_home1};Server=" & ServerName & ";DBQ=Server1;UID=" & USERLIST & ";Pwd=" & PWDLIST & ""
qdExtData.SQL = strSQL
qdExtData.Close
db.Close
Set db = Nothing
End Function
I then Set up a runcode macro called AutoExec
Ok, first up?
I would avoid (not use) a system, or a user DSN. The reasons are MANY, but these types of DSN's require not only a external reference, but also often require elevated registry rights. And worse yet, your password will be in plain view.
The best solution is to use what is called a DSN-less connection. And you can create these connections even without code!
And even better? If the server + database name is NOT changed, but ONLY the password? You can change the userID + password WITHOUT having to re-link the tables (ideal for you with a changing password, but NOT the server + database being changed).
Even better better? If you adopt a wee bit of "log on" code, then you don't have to store the password in the table links! What this means if someone decides to fire up access, and say import your linked tables? Well, for one, they will not be able to open the tables, and EVEN better yet the uid/password is NOT part of, nor is it stored in the connection string for each linked table. As noted, because of this, you can change the UID, and not have to re-link the tables.
The first step:
First up, ALWAYS (but ALWAYS!) when you link the tables, use a FILE dsn. this is imporant since when using a FILE dsn in access, they are automatic converted to DSN-less connections for you.
In other words, if you link your tables with a FILE dsn, then once the tables are re-linked, then you can even delete or toss out the DSN. And this means you can deploy the linked database (front end) to any workstation. You will not have to setup a DSN on that workstation, and in fact don't have to setup anything at all. (you will as before of course require the oracle database driver).
What the above means is when a password is updated/changed, you could then simply roll out a new front end. In fact, you likely have some auto updating ability for your application. (and if you don't', then you could (should) cobble together a bit of code to do this for you). So, you should have some means to roll out a new version of your software. After all, you REALLY have to install your "application" on each workstation LIKE you do with all other software, right???
So, there are two parts here:
Adopting a FILE dsn for the table links. As noted, once you do this, then you don't need the DSN anymore. This is great for distribution to each workstation.
Also MAKE SURE when you do link, you do NOT check the box to save the password. This is to ensure that uid/password is NOT saved in the connection strings.
So, if tables don't have uid/password, then how will they work?
Well, what you do is execute a "logon" to the database in your startup code. Once you execute this logon, then all linked tables will work! It is this "small" bit of code that can read the uid/password you place in an external file. Where you place this uid/password is up to you. It could be embedder in the code, or even some external text file that you read on startup. And it could even be a local table in the front end. (this idea would work well if you have some kind of automatic update system for when you roll out the next great version of your software.
So, with the ability to execute a logon, and not having to re-link the tables, then we have a EASY means to change the password.
So, you have to:
go dsn-less. Thankfully, access does this by default, but ONLY if you use a FILE dsn.
Get/grab the code to execute a logon to the database. In fact, you likly have to delete all your table links. Exit Access, then re-start Access. Now, run your logon code, and THEN re-link your tables (using a FILE dsn you make).
The code to execute a logon is this:
Function TestLogin(strCon As String) As Boolean
On Error GoTo TestError
Dim dbs As DAO.Database
Dim qdf As DAO.QueryDef
Set dbs = CurrentDb()
Set qdf = dbs.CreateQueryDef("")
qdf.connect = strCon
qdf.ReturnsRecords = False
'Any VALID SQL statement that runs on server will work below.
qdf.sql = "SELECT 1 "
qdf.Execute
TestLogin = True
Exit Function
TestError:
TestLogin = False
Exit Function
End Function
The above of course requires a correctly formed conneciton string.
So, to make ALL of this work, you can adopt the FILE dsn, and use above. You will likly cobbile together some code to build you a connection string. Then add to your code some code to read an external ext file, or have the UID/password in some table. This logon code as per above has to run BEFORE any form or linked table is used or touched.
The whole process is simple, but only if you break down this into the correct steps.
How this logon trick, and example code works is not complex, but a full article explaining this approach is outlined here
Power Tip: Improve the security of database connections
https://www.microsoft.com/en-us/microsoft-365/blog/2011/04/08/power-tip-improve-the-security-of-database-connections/

How to get the SQL server linked tables are connected to using VBA?

Is there a way to know which SQL Server the linked tables in MS Access database are pointing to using the ODBC connection?
I used the code below but I got the database name only and not the SQL server name.
Private Function checkconn()
Dim strConnect As String
Dim lngLocation As String
strConnect = CurrentDb.TableDefs("dbo_buh_summary").Connect
lngLocation = InStr(strConnect, ";DATABASE=")
If lngLocation <> 0 Then
GetDataPath = Mid(strConnect, lngLocation + 10)
End If
End Function
Assuming you used a FILE dsn to original link the tables?
(or a DSN less). I strong, but rather strong recommend you link always using a FILE dsn (not system or user). The reason is Access converts these links to DSN-less for you automatic. (and thus you don't need to setup a DSN on each computer).
Having noted the above? You can grab the server and the database name with this:
Sub m34343()
Dim strCon As String
strCon = CurrentDb.TableDefs("dbo_tblHotels3").Connect
Debug.Print strCon
Debug.Print Split(Split(strCon, "SERVER=")(1), ";")(0)
Debug.Print Split(Split(strCon, "DATABASE=")(1), ";")(0)
End Sub
Output:
ODBC;DRIVER=SQL Server;SERVER=ALBERTKALLAL-PC\SQLEXPRESS;
Trusted_Connection=Yes;APP=Microsoft Office 2010;DATABASE=test3
ALBERTKALLAL-PC\SQLEXPRESS
test3
So, I in above printed out the connection string, but then the next two lines grabs the server and the database name.

DSNless connection to Oracle database using DAO Database object in VBA

it's possible to use DSNless connection with wiht an object created from DAO Database class in VBA.
The connection to database using ODBC connection works as expected, however if you use other connection string types as mentioned www.connectionstrings.com the connection is not established.
public Sub dbConnectTest()
Dim myDB As DAO.Database
Dim conn As String
Dim tns As String
Dim odbcString as String
odbcString = "ODBC;DSN=Location Name;UID=ANUSER;PWD=apassword;DBQ=A_TNS_NAME"
' this part works
Set myWorkspace = DBEngine.CreateWorkspace("APPNAME", "admin", "")
Set myDB = myWorkspace.OpenDatabase(Name:="", Options:=dbDriverNoPrompt, ReadOnly:=True, _
Connect:=odbcString)
' same here
Set myDB = OpenDatabase("", False, False, "ODBC")
' any of below part don't work
odbcString = "Driver=(Oracle in XEClient);dbq=server:1980/SID;UID=ANUSER;PWD=apassword;"
odbcString = "Driver={Oracle in OraHome92};Dbq=A_TNS_NAME;UID=ANUSER;PWD=apassword;"
odbcString = "Driver={Microsoft ODBC for Oracle};CONNECTSTRING=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=server)(PORT=1980)))(CONNECT_DATA=(SERVICE_NAME=SID)));Uid=ANUSER;Pwd=apassword;"
Set myDB = OpenDatabase("", False, False, odbcString)
end sub
I want to change the connection string due to the fact that even if myDB object is set to nothing after a user logout, when a new login is requested with a new password the old connection string is somehow preserved and instead of a connection error a successfully connection object is retrieved.
I was able to connect to an Oracle 11g instance using the following connection string and call to OpenDatabase. I'm using the version of DAO available through the reference "Microsoft Office 16.0 Access database engine Object":
' Construct connection string
oracxnstr = "Driver={Microsoft ODBC for Oracle};Server=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=fake.url.com)(PORT=fakePortNo))(CONNECT_DATA=(SID=fakeSID)));Uid=fakeUid;Pwd=fakePw;"
I've obviously used fake parameters in this string so I'm not exposing my database.
' attempt to connect to oracle
Set oradb = dbws.OpenDatabase("", 1, True, oracxnstr)
The Microsoft DAO documentation is woefully inadequate, so I'm pointing out the differences between my code and yours that might be relevant:
I'm using the connection string parameter "Server" instead of "CONNECTSTRING." However, either one works in my system.
I'm using the connection string parameter "SID" instead of "SERVICE_NAME." This also did not make a difference... this time. But for reasons I don't understand, I know that it has made a difference in the past. I don't understand why it does sometimes make a difference. (I'm an Oracle novice but I think the Oracle configuration has something to do with it.)
For the 2nd parameter to the OpenDatabase method, I'm using 1 instead of true. This is the dbDriverNotPrompt enumerated constant. If I change to true, this also doesn't make a difference.
If I use DAO 3.6 I do get a run-time error 3151 "ODBC connection failed." I'm wondering if the older version isn't able to handle DSN-less or TNS-less connection strings to Oracle?
The only other difference I can think of is that maybe your Oracle username/password account has Read Only permissions, while the 3rd parameter to the OpenDatabase method is set to false?

IsSysAdmin on vb.net?

I'm converting old VB6 application to Vb.net appl. And just wanted to know is there wasy to check isSysAdimin in vb.net?
**VB6 code:**
Set oSQL = New SQLServer
oSQL.LoginSecure = True
oSQL.Connect "" & "xxxxxxx"
If oSQL.Issysadmin Then DBA = True
**VB.Net code:**
Dim srvConn As New ServerConnection()
srvConn.ServerInstance = "" & "xxxxxxx"
srvConn.LoginSecure = True
Dim oSQL As New Server(srvConn)
If oSQL.IsSysAdmin? Then DBA = True
According to technet.microsoft.com...
*This feature will be removed in a future version of Microsoft SQL Server. Avoid using this feature in new development work, and plan to modify applications that currently use this feature.
The Issysadmin property reports membership in the fixed server role sysadmin for the SQL Distributed Management Objects (SQL-DMO) connection.
On another note, this has been answered using LINQ here...

Is there a VB.NET equivalent of PrivateDBEngine from VB6?

Hi I don't have experience with VB6 or VB.NET but am trying to convert some old code to .NET. The VB6 uses PrivDBEngine.
Public oDbEngine As New PrivDBEngine
After some googling this looks like DAO. I was told to replace its usage with ADO.NET. I pasted every spot I see it in the code below as a reference in case it helps. I'll get to googling "PrivateDBEngine DAO to ADO.NET" but if anyone knows of an equivalent in ADO.NET or even has some useful links please let me know. Should I be looking into DataSet? Thank you very much for your time and patience. Other places I encounter it are:
' Build the proper connection string. If ODBC, the
' options line of the OpenDatabase method accepts the
' connection string. If Access, just pass in the
' filename
sPassword = Password
Select Case ConnType
Case DBTYPE_ACCESS
DBFilename = ConnectString
If (Len(UserName) = 0 And Len(Password) <> 0) Then
DBOptions = ";PWD=" + Password
sPassword = ""
Else
DBOptions = ""
End If
If (UserName = "") Then
UserName = "Admin"
Else
UserName = UserName
End If
If (Len(SystemMDB) <> 0) Then
---> oDbEngine.SystemDB = SystemMDB <-----------
End If
And also:
' Handle UserName and Password.
Set oWorkSpace = oDbEngine.CreateWorkspace("Test", UserName, sPassword)
And lastly:
Sub CleanUpDBConnection()
On Error Resume Next
' Close the recordsets
grsIndexTable.Close
grsDocTable.Close
' Close the database
If Connected Then
DBConnection.Close
Set DBConnection = Nothing
oWorkSpace.Close
Set oWorkSpace = Nothing
Set oDbEngine = Nothing
CurrentDTable = ""
CurrentITable = ""
Connected = False
End If
End Sub
PrivDBEngine is part of DAO. It's similar to DBEngine.
In an application, you may need to connect to multiple databases with different workgroup security connections. The PrivDBEngine lets you do that separate from DBEngine.
A common scenario is the main database (connected via DBEngine) which has data pointing to other databases, each with their own workgroup security settings. In that case, PrivDBEngine would be use to open those databases.
Off the top of my head, I can't remember if you can support 3 workgroup security settings at one time, but you can certainly reset the PrivDBEngine variable as needed without impacting all the recordsets already open using the DBEngine variable.
You should use the same ACE/DAO/DBEngine code in VB.NET if you are using Access databases. ADO can replace some ACE/DAO code, especially if you're using SQL Server and just retrieving data, but if you're using Access databases, ACE/DAO supports features that ADO doesn't.