Where can I obtain high quality information about ODBC & Access Databases? - c++

Where can I obtain high quality information about ODBC & Access Databases?
I have worked on various projects over the years using ODBC from MFC/C++/Java.
Currently, I have a project in C++/MFC that uses a customized MFC layer to interface dynamically to an ODBC DSN connected to an Access 2000 dbm file.
This generally works.
However, I commonly get warnings such as:
DBMS: ACCESS Version: 04.00.0000 ODBC Driver Manager Version:
03.80.0000 Optional feature not implemented State:S1C00,Native:106,Origin:[Microsoft][ODBC Microsoft Access
Driver]
Warning: Driver does not support requested concurrency. Optional
feature not implemented
State:S1C00,Native:106,Origin:[Microsoft][ODBC Microsoft Access
Driver]
and now, I get the following when our software attempts to create a view:
General Warning Unable to open registry key 'Temporary (volatile) Jet
DSN for pr ocess 0x18fc Thread 0xc0 DBC 0x8c4cfc Jet'.
State:01000,Native:1,Origin:[Microsoft][ODBC Microsoft Access Driver]
DBMS: ACCESS Version: 04.00.0000 ODBC Driver Manager Version:
03.80.0000 Executing SQL: create view SPEC as select CALNAME as TEST, CARDNUMBER, CARTONSTYLE as CARTON, CCAL as FLUTE, CORRDIR,
CUSTOMERID, DESCRIPTION as DESCRIPTIO, DESIGNER, DESIGNNUM, JOINTSIZE,
JOINTTYPE, PANEL_D as DEPTH, PANEL_L as LENGTH, PANEL_W as WIDTH,
RULRULX as DSIZEX, RULRULY as DSIZEY, SHEETUX as SIZEX, SHEETUY as
SIZEY, SHEETX as GROSSX, SHEETY as GROSSY from "Designs" where
DESIGNNUM is not null
Warning: ODBC Success With Info, Driver's
SQLSetConnectAttr failed State:IM006,Native:0,Origin:[Microsoft][ODBC
Driver Manager]
General Warning Unable to open registry key 'Temporary (volatile) Jet
DSN for pr ocess 0x18fc Thread 0xc0 DBC 0x8c4cfc Jet'.
State:01000,Native:1,Origin:[Microsoft][ODBC Microsoft Access Driver]
For the first part, regarding warnings concerning optional feature not implemented, and concurrency state not implemented (perhaps the same underlying issue), I have no idea what concurrency feature my software is even asking for? What concurrency states are appropriate? How does one ask for the "correct" one? Is there a table for versions of Windows vs. appropriate concurrency state to request?
For the second part, regarding the specific failure to create a view due to failure to open a registry key: huh?! Who is failing to open what registry key?
I have found some information concerning the need to give IUSR full permissions on the "windows NT temp folder". This sounds like a horrible issue for a desktop application to need to concern itself with. How should a desktop application, using an ODBC DSN ever need to concern itself with user permissions when manipulating a database file which exists in a user read/write-able path? What more permissions are necessary to allow the user to execute this SQL? And since the user is already able to add and delete columns and rows in the existing tables in the database, what more needs to be done?
This code used to work under XP. So I have to assume that Vista and/or Win 7 added some security that now blocks this functionality.
I am interested in:
Canonical reference material from Microsoft that actually documents their various ODBC Access interfaces, options, versions, host-issues, etc.
Specific information regarding the warnings regarding concurrency.
Specific information regarding the apparent permissions failures when trying to create a view in the access 2000 dbm.
Suggestions for modernizing the above, sans a complete overhaul or technology replacement. i.e. I would happily update the Access file to 2003 or 2007 or whatever, or possibly switch the back-end to SQL Server Lite, but I cannot justify changing from ODBC to some replacement middleware (it's just not worth the time & risk).
Thanks for any ideas or help you may have to offer.

we have an application that dynamically make use of ODBC access databases.
Microsoft has good documentation about odbc
http://msdn.microsoft.com/en-us/library/s9ds2ktb(v=vs.80).aspx
You should also take a look at the CRecordset and CDatabase documentation
http://msdn.microsoft.com/en-us/library/1hkkwdf0(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/2dhc1abk(v=VS.80).aspx
For the concurrency issue, it often occurs when you open a CRecordset with the wrong options. Where I work, we usually open recordsets with the following options
RecordsetToUse.Open(CRecordset::dynaset, "SQL Statement or NULL to use the DefaultSQL", CRecordset::skipDeletedRecords);
If using the recordset for fast readonly access, you can also use
RecordsetToUse.Open(CRecordset::forwardOnly, "SQL Statement or NULL to use the DefaultSQL", CRecordset::readOnly);
3 . For the Create View problem, It seems that ODBC doesn't support the creation of views... I think, on the other hand, that you could use ADODB (http://www.codeproject.com/KB/database/adoclasses.aspx) to do that

Yeah, the migration of remote clients can be a pain. Part of the reason why I absolutely try to avoid Access at all costs. I've done this one of two ways.
Use WebEx (or some other online meeting program) to grab control of the remote machine to insure the migration goes as needed.
Build into the new code a check to see if database has been migrated.
If the new DB (SQL Server) shows as not found, then the app fires off the migration tool. However, this means building and perfecting a migration utility and scripts to automate the migration as nay number of things can go wrong.
One thing I did start doing a while ago is building an app compatibility table into the DB. That way the code can check to make sure the DB schema version matches. I also include another table (encrypted) with all the necessary SQL to upgrade (migrate) the DB to the new version. That way, the app can determine that the DB needs to be migrated and can run through the scripts to do it.
I really hope this helps.

Related

Cannot access power plans via WMI

I am trying to enumerate Windows power plans through very straightforward code that has been working for several years. On my Windows 10 64-bit machine, however, I am getting errors when I try to enumerate a collection of power plans.
I realize Visual Foxpro code is like a fossil, but it is still pretty easy to read:
loSchemes = CREATEOBJECT("Collection")
loWMIService = GETOBJECT("winmgmts:\\.\root\cimv2\power")
loItems = loWMIService.ExecQuery("SELECT * FROM Win32_PowerPlan")
FOR EACH loItem IN loItems
loSchemes.Add(loItem)
ENDFOR
The code has been working for years, from Windows XP up through (I think, anyway), Windows 10.
The error happens after loItems is instantiated via the ExecQuery() method call. The object exists and has visible properties, but if I try to access anything in the debugger, it says the expression cannot be evaluated. If I wrap the iterating FOR loop in a TRY..CATCH, the error I get is:
OLE error code 0x80070668: Only administrators have permission to add,
remove, or configure server software during a Terminal services remote
session. If you want to install or configure software on the server,
contact your network administrator.
So, it looks like I am being locked out from power plan information because the process thinks I am remotely trying to change the configuration even though I am accessing WMI data from the local machine (where I do have administrator rights, incidentally).
I downloaded a "WMI Explorer" tool from Code Plex, and I actually get the same problem there when I try to iterate over Win32_PowerPlan. The log returns an error:
Failed to enumerate instances from Win32_PowerPlan. ERROR:
(That is the literal response -- no actual error is listed.)
This makes me think this isn't just some sort of Foxpro issue.
Edit
I downloaded a WMI process explorer from Sapien, and it displays a UAC prompt every time it starts, running it with elevated privileges. Both the 32-bit and 64-bit versions of that software can query Win32_PowerPlan and display results. I then ran the Code Plex WMI Explorer as administrator and it was also able to iterate over Win32_PowerPlan without errors. So, the issue appears to be unrelated to "bit"-ness and has everything to do with WMI data access requiring administrator privileges even though I am running locally using a login that does, in fact, have administrator privileges. Needless to say, I am still stumped... For the record, I can still access all sorts of other information via WMI: processor info, memory usage, processes, services, IP Address, and OS description. All of those modules still work perfectly. But when it comes to the \root\cimv2\power namespace and accessing power plans, no joy.
Further edit
Some other questions mention ImpersonationLevel, saying I might need to explicitly set the level to "impersonate" (an enumeration constant = 3). I am playing with my WMIService object and can read and write the impersonation level, but it is 3 by default. I raised it to 4 ("delegate") and still cannot access the power plan items. The query runs fine, but an error gets thrown when I try to access any properties of loItems. If I reduce the impersonation level to 1 ("anonymous"), then an "Access denied" error gets thrown on the ExecQuery() call. Finally, level 2 ("identify") allows the query and I can access the Count property without an error being thrown. But zero items are returned where there should be 5. I am confused now more than ever.
In summary, I cannot access power plan information from my local machine, even though I have administrator privileges, regardless. This is on a Windows 10 Professional 64-bit installation (all updates up-to-date), definitely no Terminal Server software installed.

MS Access database SQL query issue in windows 10

I have been using MS access database ( *.MDB) in a 64-bit format in windows 7 (64-bit) for quite some time. The Access SQL is called from a C++ module.
I have recently upgraded my OS to windows 10, I am still able to open connection to the ODBC (user DSN in this case), however, it seems my earlier program can no longer open the table or run queries. I am unsure what are my options now, please advice.
Should I use .accdb in place of .mdb ?
Try changing provider in connection string : "Provider=Microsoft.Jet.OLEDB.4.0;" Like this if not yet done so.
After testing I found that changing from .mdb to
.accdb did solve the problem. I am posting so that I can close this thread and perhaps benefit someone.

Writing to the Windows Security Log with C++

I have been tasked with writing entries to the Windows security log. The entire project is Win32 C++ code. I have already written (with help from various online resources) a logging class that handles registration, deregistration, and code for executing the ReportEvent() call. Also, I've done the mc.exe and rc.exe steps for my event logging, if that helps establish where I'm at in the project.
My question is a multi-parter:
I've noticed at Filling Windows XP Security Event Log that there are some who believe this is not allowed by Windows. Others ( How to write log to SECURITY event Log in C#? ) imply otherwise. Possible or not?
If it is possible, how to get it to write to the security log. Is it as simple as specifying "Security" as my source name when calling RegisterEventSource()?
As far as deregistration, when should that occur? When the app is uninstalled? When the app closes? When the log entry is written?
How do I look up my log entries? I look in the Windows Event Viewer, but I don't see the entries I add with my test app, despite all the appropriate return values from the system calls. Where would I look up the events that I specified with a source name of "yarp" when I made my call to RegisterEventSource()?
For the moment, I'll just deal with the first question, because the answer to that probably renders the rest irrelevant.
Only Local Security Authority (lsass.exe) can write to the security log. This isn't a matter that something else attempting to get the privilege will fail -- it's a matter of there not being a way for anything else to even request the privilege at all (and this is by design).
From there, about the only answer to your other questions is "Sorry!"

Using SQLite with WinRT

I am developing a metro ui application and I would like to use SQLite for some internal data instead of JET in order to take advantage of some already-written code.
Howerver when I try to use sqlite3_open for opening a data base, it does not work. I get an error saying a cannot open the data base.
I believe some APIs used by the SQLite cannot be used on metro style application.
Can someone help me on this? At least say me how to identify what apis should be ported?
This code should work:
auto localAppDataParh = Windows::Storage::ApplicationData::Current->LocalFolder->Path;
std::wstring path( localAppDataParh->Data() );
path += L"\\sample.db";
sqlite3* db;
int rc = sqlite3_open16( path.c_str(), &db);
I believe some APIs used by the SQLite cannot be used on metro style application.
might work(at least on Preview Release), but not permitted. Windows App Cert Kit says:
Error: This application failed the supported API check.
API CreateFileA in kernel32.dll is not supported for this application type.
API CreateFileW in kernel32.dll is not supported for this application type.
API DeleteFileA in kernel32.dll is not supported for this application type.
:
:
Try to open the database in the local folder. Here's a wrapper that works: http://sqlwinrt.codeplex.com/
There was just released a new WinRT SQLite3 variant, that is compatible with the Windows Store guidelines. See https://github.com/doo/SQLite3-WinRT
try this one (for UTF-8 database filenames only):
int ret = Sqlite3.sqlite3_open_v2("qq.db", out db, 1, "");
See sqlite.org for more details.
I have not tried sqllite in WinRT, but I think it should work. The most likely candidate is that you do not have the correct permissions to the file you are trying to open. Check to make sure you can open the file with a simple API like fopen(). If that fails, then it is a permissions issue. You need to have your database in a directory that your app has natural rights to. It can't be in the user's documents folder for instance.

Automatically checking for a new version of my application

Trying to honor a feature request from our customers, I'd like that my application, when Internet is available, check on our website if a new version is available.
The problem is that I have no idea about what have to be done on the server side.
I can imagine that my application (developped in C++ using Qt) has to send a request (HTTP ?) to the server, but what is going to respond to this request ? In order to go through firewalls, I guess I'll have to use port 80 ? Is this correct ?
Or, for such a feature, do I have to ask our network admin to open a specific port number through which I'll communicate ?
#pilif : thanks for your detailed answer. There is still something which is unclear for me :
like
http://www.example.com/update?version=1.2.4
Then you can return what ever you want, probably also the download-URL of the installer of the new version.
How do I return something ? Will it be a php or asp page (I know nothing about PHP nor ASP, I have to confess) ? How can I decode the ?version=1.2.4 part in order to return something accordingly ?
I would absolutely recommend to just do a plain HTTP request to your website. Everything else is bound to fail.
I'd make a HTTP GET request to a certain page on your site containing the version of the local application.
like
http://www.example.com/update?version=1.2.4
Then you can return what ever you want, probably also the download-URL of the installer of the new version.
Why not just put a static file with the latest version to the server and let the client decide? Because you may want (or need) to have control over the process. Maybe 1.2 won't be compatible with the server in the future, so you want the server to force the update to 1.3, but the update from 1.2.4 to 1.2.6 could be uncritical, so you might want to present the client with an optional update.
Or you want to have a breakdown over the installed base.
Or whatever. Usually, I've learned it's best to keep as much intelligence on the server, because the server is what you have ultimate control over.
Speaking here with a bit of experience in the field, here's a small preview of what can (and will - trust me) go wrong:
Your Application will be prevented from making HTTP-Requests by the various Personal Firewall applications out there.
A considerable percentage of users won't have the needed permissions to actually get the update process going.
Even if your users have allowed the old version past their personal firewall, said tool will complain because the .EXE has changed and will recommend the user not to allow the new exe to connect (users usually comply with the wishes of their security tool here).
In managed environments, you'll be shot and hanged (not necessarily in that order) for loading executable content from the web and then actually executing it.
So to keep the damage as low as possible,
fail silently when you can't connect to the update server
before updating, make sure that you have write-permission to the install directory and warn the user if you do not, or just don't update at all.
Provide a way for administrators to turn the auto-update off.
It's no fun to do what you are about to do - especially when you deal with non technically inclined users as I had to numerous times.
Pilif answer was good, and I have lots of experience with this too, but I'd like to add something more:
Remember that if you start yourapp.exe, then the "updater" will try to overwrite yourapp.exe with the newest version. Depending upon your operating system and programming environment (you've mentioned C++/QT, I have no experience with those), you will not be able to overwrite yourapp.exe because it will be in use.
What I have done is create a launcher. I have a MyAppLauncher.exe that uses a config file (xml, very simple) to launch the "real exe". Should a new version exist, the Launcher can update the "real exe" because it's not in use, and then relaunch the new version.
Just keep that in mind and you'll be safe.
Martin,
you are absolutely right of course. But I would deliver the launcher with the installer. Or just download the installer, launch it and quit myself as soon as possible. The reason is bugs in the launcher. You would never, ever, want to be dependent on a component you cannot update (or forget to include in the initial drop).
So the payload I distribute with the updating process of my application is just the standard installer, but devoid of any significant UI. Once the client has checked that the installer has a chance of running successfully and once it has downloaded the updater, it runs that and quits itself.
The updater than runs, installs its payload into the original installation directory and restarts the (hopefully updated) application.
Still: The process is hairy and you better think twice before implementing an Auto Update functionality on the Windows Platform when your application has a wide focus of usage.
in php, the thing is easy:
<?php
if (version_compare($_GET['version'], "1.4.0") < 0){
echo "http://www.example.com/update.exe";
}else{
echo "no update";
}
?>
if course you could extend this so the currently available version isn't hard-coded inside the script, but this is just about illustrating the point.
In your application you would have this pseudo code:
result = makeHTTPRequest("http://www.example.com/update?version=" + getExeVersion());
if result != "no update" then
updater = downloadUpdater(result);
ShellExecute(updater);
ExitApplication;
end;
Feel free to extend the "protocol" by specifying something the PHP script could return to tell the client whether it's an important, mandatory update or not.
Or you can add some text to display to the user - maybe containing some information about what's changed.
Your possibilities are quite limitless.
My Qt app just uses QHttp to read tiny XML file off my website that contains the latest version number. If this is greater than the current version number it gives the option to go to the download page. Very simple. Works fine.
I would agree with #Martin and #Pilif's answer, but add;
Consider allowing your end-users to decide if they want to actually install the update there and then, or delay the installation of the update until they've finished using the program.
I don't know the purpose/function of your app but many applications are launched when the user needs to do something specific there and then - nothing more annoying than launching an app and then being told it's found a new version, and you having to wait for it to download, shut down the app and relaunch itself. If your program has other resources that might be updated (reference files, databases etc) the problem gets worse.
We had an EPOS system running in about 400 shops, and initially we thought it would be great to have the program spot updates and download them (using a file containing a version number very similar to the suggestions you have above)... great idea. Until all of the shops started up their systems at around the same time (8:45-8:50am), and our server was hit serving a 20+Mb download to 400 remote servers, which would then update the local software and cause a restart. Chaos - with nobody able to trade for about 10 minutes.
Needless to say that this caused us to subsequently turn off the 'check for updates' feature and redesign it to allow the shops to 'delay' the update until later in the day. :-)
EDIT: And if anyone from ADOBE is reading - for god's sake why does the damn acrobat reader insist on trying to download updates and crap when I just want to fire-it-up to read a document? Isn't it slow enough at starting, and bloated enough, as it is, without wasting a further 20-30 seconds of my life looking for updates every time I want to read a PDF?
DONT THEY USE THEIR OWN SOFTWARE??!!! :-)
On the server you could just have a simple file "latestversion.txt" which contains the version number (and maybe download URL) of the latest version. The client then just needs to read this file using a simple HTTP request (yes, to port 80) to retrieve http://your.web.site/latestversion.txt, which you can then parse to get the version number. This way you don't need any fancy server code --- you just need to add a simple file to your existing website.
if you keep your files in the update directory on example.com, this PHP script should download them for you given the request previously mentioned. (your update would be yourprogram.1.2.4.exe
$version = $_GET['version'];
$filename = "yourprogram" . $version . ".exe";
$filesize = filesize($filename);
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: post-check=0, pre-check=0");
header("Content-type: application-download");
header('Content-Length: ' . $filesize);
header('Content-Disposition: attachment; filename="' . basename($filename).'"');
header("Content-Transfer-Encoding: binary");
This makes your web browser think it's downloading an application.
The simplest way to make this happen is to fire an HTTP request using a library like libcurl and make it download an ini or xml file which contains the online version and where a new version would be available online.
After parsing the xml file you can determine if a new version is needed and download the new version with libcurl and install it.
Just put an (XML) file on your server with the version number of the latest version, and a URL to the download the new version from. Your application can then request the XML file, look if the version differs from its own, and take action accordingly.
I think that simple XML file on the server would be sufficient for version checking only purposes.
You would need then only an ftp account on your server and build system that is able to send a file via ftp after it has built a new version. That build system could even put installation files/zip on your website directly!
If you want to keep it really basic, simply upload a version.txt to a webserver, that contains an integer version number. Download that check against the latest version.txt you downloaded and then just download the msi or setup package and run it.
More advanced versions would be to use rss, xml or similar. It would be best to use a third-party library to parse the rss and you could include information that is displayed to your user about changes if you wish to do so.
Basically you just need simple download functionality.
Both these solutions will only require you to access port 80 outgoing from the client side. This should normally not require any changes to firewalls or networking (on the client side) and you simply need to have a internet facing web server (web hosting, colocation or your own server - all would work here).
There are a couple of commercial auto-update solutions available. I'll leave the recommendations for those to others answerers, because I only have experience on the .net side with Click-Once and Updater Application Block (the latter is not continued any more).