# Delphi开发的数据库程序在C:\PDOXUSRS.NET生成文件，拒绝访问及读写权限

Delphi 专栏收录该内容
4 篇文章 0 订阅
﻿﻿

Permission denied.C:\PDOXUSRS.NET

PDOXUSRS.NEt为计算机根目录下的一个数据库，在文件C：盘根目录下生成。

Network initialization failed.

Permission denied.
File:C:\PDOXUSRS.NET
Directory:C:\.

State=dsbrowse时才能调用。

Query1.SQL.Text:='select field1,field2 from table1';
UpdateSQL1.ModifySQL:='update table1 set field1=:field1,field2=:field2 where field1=:old_field1 and field2=:old_field2;

Query1.Open;
Query1.First;
while not Query1.Eof  do begin
Query1.Edit;
Query1.FieldByName('field1').AsString:='123';
Query1.Post; //此时数据并未提交到后台。
Query1.Next;
end;
Query1.Database.StartTransaction
try
Query1.Database.Commit;
except
Query1.Database.Rollbback;
raise;
end;

# How to change NET DIR programmatically so it persists

Abstract: Writing values into the BDE configuration file requires only a few function calls.

## How to change NET DIR programmatically so it persists

Writing values into the BDE configuration file requires only a few function calls.

by Steven Randolph

Programs accessing Paradox tables must also access a special control file named PDOXUSRS.NET. When multiple programs, whether running on one computer or on multiple computers, access the same Paradox table(s), each program must also access the same PDOXUSRS.NET file. Therefore, if multiple computers are running the programs, the PDOXUSRS.NET file must be located in a shared directory. Usually, the location of this file is configured on each computer by running the BDE configuration utility program, BDEADMIN.EXE. The NET DIR parameter indicates where the PDOXUSRS.NET file is located. That NET DIR parameter is associated with the Paradox driver generally, not with any particular alias.

THE PROBLEM AND THE GOAL

I recently inherited the maintenance of a production system consisting of several client programs running on multiple computers. Each program accesses Paradox tables through multiple aliases. Each alias "points" to a different directory on a host computer. Each program also reads and writes flat files in a large number of directories on one of two hosts. One of the first improvements that I determined to make was to set up a test environment, which my predecessor had never done. I wanted a single host computer for the test environment to have its own tables, its own set of directories, and its own PDOXUSRS.NET file. In other words, any client computer designated for testing should be isolated from the production host environment. I also wanted to make the minimum of changes to the existing production programs to allow for this.

While it might seem that the entire task could be accomplished by changing the drive mappings on the test computers, which can be done programmatically, in my case that was not practical. Some of the same drive mappings are used for other purposes in our environment. Besides, this would have required me to create the same rather arcane relative directory structure on the test host as exists on the two production hosts, and I did not wish to do that.

So I decided to create a utility program that would accomplish several tasks at once. In this program, the user could click a button labeled "Configure for Test" or one labeled "Configure for Production" and the configuration would be made immediately on that computer. It would create or modify registry entries specifying the various directories to access for the flat files. This part was easy to program, using the TRegistry component. The program also needed to configure the several Paradox aliases to point to either test or production directories. This was also no problem; I merely used the DbiAddAlias and DbiDeleteAlias functions, both of which are well documented. The only variable parameter for the creation of the Paradox aliases was the directory location, and everything else was left at default values. Setting the last parameter in the DbiAddAlias call to "true" caused the alias to be recorded permanently in the BDE configuration file for that computer. However, doing the same for the NET DIR value was not so easy!

There is a documented technique for changing the NET DIR directory programmatically. It is documented in Borlands TI-15230. This technique uses the DbiSetProp BDE function. Unfortunately, DbiSetProp changes the NET DIR directory for the current session only! That is, it does not cause the new value for NET DIR to be written into the BDE configuration file. It took quite a bit of searching and some experimentation to determine how to do that. Finally I figured out that the code in the following block does the trick.

THE SOLUTION

First is the C++ Builder code. You might want to do the error trapping a little differently, or put in some messages, in a real program. This is just an example of the basic technique.

  if(DbiInit(NULL) == DBIERR_NONE)
{
hDBICur hCur = NULL;
{
if(DbiSetToBegin(hCur) == DBIERR_NONE)
{
CFGDesc Config;
for(;;)   // for ever
{
if(DbiGetNextRecord(hCur, dbiWRITELOCK, &Config, NULL)
!= DBIERR_NONE) break;
if(strcmpi(Config.szNodeName, "NET DIR") == 0)
{
strcpy(Config.szValue, "servervolumemydir");
DbiModifyRecord(hCur, &Config, true);
break;
}
}
}
}
DbiExit();
}

The Delphi version of this process is similar.
var
hCur : hDBICur;
Config : CFGDesc;
ContinueIt: boolean;

...

if DbiInit(nil) = DBIERR_NONE then
begin
hCur := nil;
begin
if DbiSetToBegin(hCur) = DBIERR_NONE then
begin
ContinueIt := true;
while ContinueIt do
begin
if(DbiGetNextRecord(hCur, dbiWRITELOCK, @Config, nil)
<> DBIERR_NONE) then
ContinueIt := false
else
if StrIComp(Config.szNodeName, 'NET DIR') = 0 then
begin
StrCopy(Config.szValue, 'servervolumemydir');
DbiModifyRecord(hCur, @Config, true);
ContinueIt := false
end;
end;
end;
end;
DbiExit();
end;

If you use this code, you would want to substitute your own value for the path name to be copied into Config.szValue, of course. In my real program, the value was supplied in a string variable, the contents being determined by whether the user had clicked the "test" button or the "production" button. The value you submit can contain a mapped drive letter, if you are quite sure those mappings will never change; but I always prefer to use the universal naming convention.

CAVEATS

My experimentation suggests that it is not strictly necessary to close other BDE programs prior to running this code. Just the same, it would probably be a good idea to do so. In any case, a BDE program will not take notice of a changed value in the BDE configuration file until it is started subsequent to the change. You may also notice this while debugging your utility program in the IDE, if you happen to change the value and then try to re-read it without calling DbiExit and DbiInit again. (In the example code, this should not be a problem because DbiExit is executed right after the change is written.)

Another important consideration is to make sure that the path you submit to be the new NET DIR actually exists. The BDE will, at runtime, create the PDOXUSRS.NET file if it does not already exist in the NET DIR directory; but the BDE will not create the NET DIR directory for you. If this happens, you will get a runtime error "Network Initialization Failed" when your program tries to initialize or access a Paradox object.

You should also remember that if you have programs that change their own NET DIR locations at runtime, using either the DbiSetProp function or the NetFileDir property of a TSession component, this will override the NET DIR value in the configuration file. All of the programs I inherited just use whatever value the configuration file supplies.

Finally, you should note that the same technique could be used to change other parameters for the Paradox driver, or many parameters for other drivers. You would have to be very careful about which values you supply, however. Changing the NET DIR directory is relatively safe.

 I am writing a new version of an application that has been written by someone else. The old version uses a Paradox database while my new version uses an SQLite database, which is already implemented (using a wrapper around sqlite.dll). Now I need to give my customers a way to migrate their data, but I have never used BDE (or even any Delphi database component) before, so I am quite lost. Since I'll write about three different programs, I'll call those OldVersion, NewVersion and MigrationHelper. In this MigrationHelper, I currently have a TDatabase (DriverName: STANDARD) with path set correctly in Params. I can now set Connected to true without an error message. There is also a TTable with DatabaseName set to the values of the TDatabase and TableName set to the .db-file that lies in the folder (the name was automatically filled in, I only hat to select it). Now the problem: If I set Active to true, an error message complains about missing access rights for C:\PDOXUSRS.NET. I know I could set another path using BDEADMIN, but I don't want every customer to call me for help. Furthermore, I have a test machine with OldVersion running - it can access the database without any error, while MigrationHelper throws the aforementioned error. This leads me to the suspicion there might be a workaround. This also makes me think a workaround might be possible:

• 0
点赞
• 0
评论
• 0
收藏
• 一键三连
• 扫一扫，分享海报

05-17

12-19
11-30 863
06-02 2802
02-02 2万+