Newsgroup: it.comp.lang.delphi
Titolo: [Bug] RPCRT4.DLL, Access2000, DAO2000 e TableDef (insieme TableDefs)

Ho il seguente problema con l'accesso via COM ad Access2000 (unit Access2000, 
Office2000 e DAO2000), che si ripete sia su sistemi WinXp che Win2000:
- quando tento di accedere (da codice Delphi) a un elemento dell'insieme 
TableDefs di un database, ottengo un'eccezione AV nella libreria RPCRT4.DLL
Ho provato a cercare risposte su Google, e sembra che quella DLL (Remote 
Procedure Call RunTime) sia coinvolta in un sacco di applicazioni. Inoltre, 
ho controllato sui PC d'ufficio e ogni macchina ha una versione differente 
(numero di build) di questa libreria.
Non ho trovato nulla che riguardasse il mio caso specifico.
Che fare?
Segue il modo di riprodurre il bug (Delphi7 + Win2000 o WinXp, Office2000): 
creare un database access con un numero di tabelle vuote a piacere e salvarlo 
nella stessa cartella dell'applicazione.
Creare un nuovo progetto Delphi e nella form principale scrivere questo:
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;
type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
uses
  Access2000, DAO2000;
procedure TForm1.FormCreate(Sender: TObject);
var
  app: TAccessApplication;
  s: string;
  tds: TableDefs;
  td: TableDef;
begin
  app := TAccessApplication.Create(nil);
  try
    s := IncludeTrailingPathDelimiter(ExtractFilePath(
      Application.ExeName)) + 'db1.mdb';
    if not FileExists(s) then
      raise Exception.CreateFmt('Il file "%s" non esiste!', [s]);
    app.OpenCurrentDatabase(s, True);  //True = lo apriamo in modo esclusivo
    ShowMessage(Format('CurrentDb: "%s"', [
app.CurrentDb.Name
]));
    tds := app.CurrentDb.TableDefs;
    ShowMessage(Format('Ci sono %u TableDefs', [tds.Count]));
    td := tds.Item[0]; //questa riga solleva la seguente eccezione:
  { exception class EAccessViolation with message
    'Access violation at address 7807801E in module 'RPCRT4.dll'.
    Read of address 00000010'. Process stopped. Use Step or Run to continue. 
}
    //non cambia nulla scrivere
    //  td := tds.Item[1];
  finally
    app.Free
  end
end;
end.
-- 
Mauro Falzari 
   [ 
http://digilander.libero.it/mauro.falzari
 ]
 
 "Se guardi nell'abisso, anche l'abisso guarda in te." 
   (Friedrich Nietzsche)

 Office2000 e DAO2000), che si ripete sia su sistemi WinXp che Win2000:
Ho provato il codice e mi da' l'errore 
Project Project1.exe raised exception class Exception with message 'Il file
"C:\temp\db1.mdb" non esiste!'. Process stopped. Use Step or Run to
continue.
Allora lo creo io con access (2003), rilancio il codice e questo funziona,
ritornando questi messaggi:
CurrentDb: "C:\temp\db1.mdb"
e poi
Ci sono 5 TableDefs
La riga che a te scoppia, a me non da' nessun problema.
Debuggandola (click destro, menu' debug->evaluate/modify) ottengo
"Pointer($165D2C) as TableDefs" 
Nulla da eccepire, quindi, pero'...io mi ricordo che su google groups
c'erano dei modi alternativi di creare from scratch un db access, senza
passare per questa unit access2000 che non conosco. Mi ricordo che avevo
trovato riferimenti alla type library ADO_TLB o simili.
Ho googlato prima di spedire e comincia a controllare da qui:
http://tinyurl.com/cwqag
Facci sapere.
ciao
-- 
Morde. 
FAQ di icld (beta-version): 
http://icld.altervista.org
 
M-List di icld: 
http://it.groups.yahoo.com/group/icld/

 
http://tinyurl.com/cwqag
interessante, grazie. Ora ho importato anch'io la "msadox.dll" nella
ADOX_TLB e vedr? cosa riesco a cavarne fuori. Se non altro ?
un'alternativa.
Mauro Falzari.

 un'alternativa.
E' proprio questo che intendevo: se non riesci a risolvere, accertati di
avere un'altra alternativa che ti possa togliere dall'inghippo...
Gli americani ci insegnano che ci deve sempre essere un "piano B".
:-D
Ciao


 gratuito fino a 50 Mb/mese</OT>
per notizia: TeraNews č leeento (almeno cosě lo trovo io che prima ero 
abituato con 
powernews.libero.it


 abituato con 
powernews.libero.it
Se lu usi per lavoro vale la pena sganciare i 10 euro per
http://news.individual.net/
 e vedrai che non hai problemi di lentezza e hai
la certezza della pubblicazione. I ng binari non sono pero' supportati.
Ciao


 
http://news.individual.net/
 e vedrai che non hai problemi di lentezza
non ricordo quanto tempo fa, ma a un certo punto il mio account free su 
news.cis.dfn.de
 smise di funzionare, con un messaggio del server che diceva 
di trasferirsi su 
news.individual.de
Detto, fatto. 
Un paio di settimane fa è successo che anche lì l'account non permetteva più 
l'accesso.
10 Neuro all'anno non sono molti. 
Se non ricordo male però la gerarchia free.* non è supportata.
Beh neanche 
free.teranews.com
 la supporta pienamente, se per questo.
Per esempio free.it.enkey (frequentatissimo NG su eMule) non è supportata.
Per eventuali seguiti di questa discussione OT, ti proporrei di rispondermi 
su email. Ciao.


 Gli americani ci insegnano che ci deve sempre essere un "piano B".
volevo ringraziarti, perchč mi hai tolto davvero da un'impasse.
Ora riesco a manipolare tranquillamente i campi (Columns in ADOX).
Il tuo suggerimento mi č stato prezioso. Grazie.
===============================================================
uses
  ADOX_TLB;
procedure TForm1.FormCreate(Sender: TObject);
const
  DB_NAME       = 'db1.mdb';
  TABLE_NAME    = 'Tabella1';
  FIELD_NAME    = 'Testo';
var
  c: Catalog;
  s, ConnectionString: string;
  tbl: ADOX_TLB.Table;
  col: Column;
  i: Integer;
begin
  s := IncludeTrailingPathDelimiter(ExtractFilePath(
      Application.ExeName)) + DB_NAME;
  Assert(FileExists(s));
  ConnectionString := 'Provider=Microsoft.Jet.OLEDB.4.0';
  ConnectionString := ConnectionString + ';Data Source=' + s;
  ConnectionString := ConnectionString + ';Jet OLEDB:Engine Type=4';
  c := CoCatalog.Create;
  c.Set_ActiveConnection(ConnectionString);
  i := 0;
  while i < c.Tables.Count do
    if SameText(c.Tables.Item[i].Name, TABLE_NAME) then
      Break
    else
      Inc(i);
  Assert(i < c.Tables.Count);
  tbl := c.Tables.Item[i];
  i := 0;
  while i < tbl.Columns.Count do
    if SameText(tbl.Columns.Item[i].Name, FIELD_NAME) then
      Break
    else
      Inc(i);
  if i >= tbl.Columns.Count then
  begin
    col := CoColumn.Create;
    col.Name := FIELD_NAME;
    col.DefinedSize := 30;
    col.type_ := adVarWChar;
    tbl.Columns.Append(col, adVarWChar, 10);
  end;
end;


 Il tuo suggerimento mi č stato prezioso. Grazie.
Ne sono felice :)
ciao
