Newsgroup: it.comp.lang.visual-basic
Titolo: Calcolo dello spazio su disco

Per calcolare lo spazio su disco, ho sempre utilizzato la funzione
GetDiskFreeSpace, contenuta nel file Kernel32.dll. Dopo tempo fa, tuttavia,
ho scoperto che tale funzione riporta valori errati con unità più grandi di
2 Gigabyte; essa è ormai stata sostituita da GetDiskFreeSpaceEx,
disponibile solo con la versione OSR2 di Windows 95. Dopo questa doverosa
premessa, passo subito alle domande: la dichiarazione della funzione è
rimasta la stessa? Ho saputo che tale funzione utilizza valori a 64 bit che
VB non è in grado di gestire: è vero? Se sì, come ovviare al problema?
Grazie in anticipo a tutti quelli che vorranno aiutarmi.
Marco Minerva

...

La dichiarazione è:
Declare Function GetDiskFreeSpaceEx& Lib "kernel32" Alias
"GetDiskFreeSpaceExA" (ByVal lpRootPathName As String,
lpFreeBytesAvailableToCaller As LARGE_INTEGER, lpTotalNumberOfBytes As
LARGE_INTEGER, lpTotalNumberOfFreeBytes As LARGE_INTEGER)
dove LARGE_INTEGER è un tipo di dato composto da due long 64 bit
Type LARGE_INTEGER
    lowpart As Long
    highpart As Long
End Type
il numero lo dovresti poi ricavare (supposto Pippo una variabile
Large_INTEGER) nel seguente modo:
numero =  Pippo.highpart*2^32 + Pippo.lowpart
Di seguito la spiegazione dei parametri
lpDirectoryName
Pointer to a null-terminated string that specifies a directory on the disk
of interest. This string can be a UNC name.
If lpDirectoryName is NULL, the GetDiskFreeSpaceEx function obtains
information about the disk that contains the currect directory.
Note that lpDirectoryName does not have to specify the root directory on a
disk. The function accepts any directory on the disk.
lpFreeBytesAvailableToCaller
Pointer to a variable to receive the total number of free bytes on the disk
that are available to the user associated with the calling thread.
If the operating system implements per-user quotas, this value may be less
than the total number of free bytes on the disk.
lpTotalNumberOfBytes
Pointer to a variable to receive the total number of bytes on the disk.
lpTotalNumberOfFreeBytes
Pointer to a variable to receive the total number of free bytes on the disk.
This parameter can be NULL.
Return Values
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero.
Non la ho mai provata quindi non ti posso dare ulteriori informazioni
Ciao Bruno


Ho provato la nuova funzione; tuttavia, non riesco a farla funzionare
correttamente: mi spiego meglio. Dopo aver inserito la dichiarazione in un f
orm, ho digitato la seguente procedura nella ruotine Form_Load
Dim Funzione
Dim ByteDisponibili As LARGE_INTEGER, ByteTotali As LARGE_INTEGER,
ByteLiberiTotali As LARGE_INTEGER
Funzione = GetDiskFreeSpaceEx("C:\", ByteDisponibili, ByteTotali,
ByteLiberiTotali)
MsgBox "Risultato funzione: " & Funzione, 48
MsgBox "Spazio disponibile: " & Format(ByteLiberiTotali.highpart * 2 ^ 32 +
ByteLiberiTotali.lowpart, "###,###"), 48
MsgBox "Capacità totale: " & Format(ByteTotali.highpart * 2 ^ 32 +
ByteTotali.lowpart, "###,###"), 48
Lo spazio disponibile è corretto, mentre la capacità totale è errata (viene
visualizzato addirittura un numero negativo). La dimensione dell'unità C:
riportata in Risorse del computer è 3.242.950.656 byte (3,01 GB). Al
contrario, se provo ad eseguire la funzione sull'unità a dischetti o sul
drive per CD-ROM, entrambi i valori riportati sono corretti.
Qualcuno può nuovamente aiutarmi per risolvere questo inconveniente? Ciao a
tutti
Marco Minerva

Format(ByteLiberiTotali.highpart * 2 ^ 32 + ByteLiberiTotali.lowpart,
"###,###")
internamente i calcoli vengono implicitamente eseguiti sul tipo Long...
Per i calcoli potresti usare in modo esplicito un tipo numerico piu'
"grosso", ad esempio il Currency o, addirittura, il Decimal.
Quindi usi un Currency per farti i tuoi calcoli e poi lo visualizzi con
Format().
--
Roal Zanazzi
z...@iol.it

 ByteLiberiTotali.lowpart, "###,###"), 48
Per calcolare il valore fai cosi':
Dim Valore as dounble
Valore = (ByteLiberiTotali.highpart and &H7FFFFFFF) * 2 ^ 32 + ByteLiberiTotali.lowpart
Valore = Valore + iif( (ByteLiberiTotali.highpart and &H80000000), 2 ^ 31,0)
MsgBox "Spazio disponibile: " & Format(Valore, "###,###"), 48
L'ho scrotta al volo, ma dovrebbe funzionare.
-- 
Hi, Ciao
Ettore                 By -MES-
http://freeweb.aspide.it/freeweb/ilmes
Il sito comune di programmatori VB
http://members.xoom.com/it_lang_vb


Finalmente penso di aver risolto il problema. Seguendo il consiglio di Roal,
ho  modificato il tipo di "LARGE_INTEGER", definendo la variabile "lowpart"
come "Currency". In seguito, per calcolare lo spazio totale disponibile
sull'unità, ho moltiplicato tale valore per 10.000. In poche parole, ho
sostituito l'istruzione
Format(ByteTotali.highpart * 2 ^ 32 + ByteTotali.lowpart, "###,###") - dove
"ByteTotali.lowpart" era "Integer"
con l'istruzione
Format(ByteTotali.highpart * 2 ^ 32 + ByteTotali.lowpart * 10000,
"###,###") - dove "ByteTotali.lowpart" è "Currency"
In questo modo, viene riportato il valore corretto anche con il mio disco
rigido, che ha capacità di 3,01 GB (in Risorse del computer). Come in
precedenza, i valori relativi ai dischetti ed ai CD-ROM sono esatti. La mia
domanda (che spero sia l'ultima relativa a questa funzione) è la seguente:
la nuova istruzione che ho trovato è valida sempre, o magari per le unità
maggiori di 10 GB è necessario moltiplicare per 100.000?
Ancora una volta, grazie in anticipo.
Marco Minerva

 L'ho scrotta al volo, ma dovrebbe funzionare.
Infatti rivedendola..... questa non funzionera' mai!  :-(
Ci riprovo:
( Anche questa scritta al volo :-) )
Dim Valore as dounble
Valore = ULongToDouble( ByteLiberiTotali.highpart ) * 2 ^ 32 + ULongToDouble( ByteLiberiTotali.lowpart )
MsgBox "Spazio disponibile: " & Format(Valore, "###,###"), 48
Function ULongToDouble( Byval Ulong as Long ) as Double
	Dim Valore as double
	Valore = (Ulong and &H7FFFFFFF)
	If (Ulong and &H80000000) then
		Valore = Valore + 2 ^ 31
	End If
	ULongToDouble = Valore
End Function


...

Mmmmmhhhh quel 10000 puo' decisamente dare problemi.
E poi, sei sicuro che il valore risultato sia corretto?
Mettiamo che highpart = 2, lowpart = 10
che darebbe una dimensione di:  2 * (2 ^ 32)  +  10  =   
8589934602
tu invece fai: 2 * (2 ^ 32) =  
8589934592
  (ma dovrebbe venire troncato a
Long, o no?)
+ 10 * 10000 = 100000
=  alla fine il risultato dovrebbe essere completamente sbagliato...
O c'e' qualcosa che mi sono perso?
Comunque io intendevo consigliarti di fare cosi' (un esempio si capisce
meglio):
Dim temp As Currency
temp = ByteTotali.highpart * (2 ^ 32)
temp = temp + ByteTotali.lowpart
Format(temp, "###,###")
Ossia usare una variabile temporanea di tipo Currency su cui fare i calcoli.
--
Roal Zanazzi
z...@iol.it

Ettore                 By -MES-
----------------------------------------------------------------------------
----------------
Grazie Ettore, hai risolto il mio problema. Ciao e... a buon rendere!
Marco Minerva
P.S. Ho saputo che sei tu l'attuale webmaster del sito comune dei
programmatori VB: complimenti, le informazioni sono precise e semplici da
raggingere. Mi raccomando, continua cosě!