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

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


Delphi开发的数据库程序在C:\PDOXUSRS.NET生成文件,拒绝访问及读写权限, "无法打开 PARADOX.NET。这个文件可以随便删除的,下次会自动产生。

Permission denied.C:\PDOXUSRS.NET

如果用于没有对C:\PDOXUSRS.NET的写权限,系统就会报错。

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

果你装了Delphi编的程序,而它用的是Paradox数据库,就会出现这样的问题。我使用BDE访问Oracle数据库也会出现此问题。


可以改变这个文件的存放位置

如Tdatabase1.session.netfiledir:=d:\abdd\;或者存放在自己程序的目录,这样就不会有权限的问题了。还有几个属性NetFileDir、PrivateDir和ConfigMode属性。

我发现当Tquery1.CachedUpdates:=true;时就要产生这个文件。


Network initialization failed.

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

ExeSQL是直接执行SQL语句,而与CachedUpdates没有任何关系。

CachedUpdates是指对TTable或TQuery中的已修改的数据进行缓存,直到调用
ApplyUpdates.

ApplyUpdates是对TQuery或TTable中已修改,但为提交的数据进行提交,
并且只有在TQuery或TTable对象的CachedUpdates=True且Active=True,
State=dsbrowse时才能调用。

TQuery的CachedUpdates必须陪合TUpdateSQL控件才能使用。
例如:
    Query1.SQL.Text:='select field1,field2 from table1';
    Query1.CachedUpdates:=True;
    Query1.UpdateObject:=UpdateSQL1;
    UpdateSQL1.InsertSQL:='insert table1(field1,field2) values (:field1,:field2)';
    UpdateSQL1.deleteSQL:='delete from table1 where field1=:field1,field2=:field2';
    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.ApplyUpdates;
      Query1.Database.Commit;
   except
      Query1.Database.Rollbback;
      raise;
   end;  
   Query1.CommitUpdates;



Paradox数据库文件放在一服务器上的某一共享目录下,当一个用户在访问, 另一用户打开文件时会显示“Pdoxusrs.Lck 被其它用户使用.
, Paradox.Lck, PdoxUsrs.Lck
文件是用来控制纪录或文件锁定的。paradox就靠它知道当前纪录有谁在用。
这是系统文件可以不必管它。



How to change NET DIR programmatically so it persists

By: Steven Randolph

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(DbiOpenCfgInfoList(NULL, dbiREADWRITE, cfgPersistent,
            "\\DRIVERS\\PARADOX\\INIT", hCur) == DBIERR_NONE)
    {
      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;
    if DbiOpenCfgInfoList(nil, dbiREADWRITE, cfgPersistent,
        '\\DRIVERS\\PARADOX\\INIT', hCur) = DBIERR_NONE then
    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.


Opening Paradox database; 'PDOXUSRS.NET' workaround?

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
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值