File.Move [C#]

venerdì 05 dicembre 2008 - 11.47

kintaro Profilo | Junior Member

Ciao a tutti,
ho un application service che man mano che elabora i file li sposta in una cartella di archivio.

tutti i file si trovano in un unica directory e sono accumunati per gruppo dalla substring delle prima 2 lettere del file

i file sono 8 per ogni gruppo e i gruppi 6

finita l'elaborazione di ogni gruppo mi sposto gli 8 file :

foreach (string myfile in myfiles)
{
Console.WriteLine(myfile);
if (!File.Exists(PathFile + "\\" + PathArchivio + "\\" + Path.GetFileName(myfile)))
File.Move(myfile, PathFile + "\\" + PathArchivio + "\\" + Path.GetFileName(myfile));
else
Console.WriteLine("WARNING : controllo dela cartella di archivio per file doppi! (" + Path.GetFileName(myfile) + ")");
}

la cosa assurda è che per ogni gruppo mi sposta solo 2 file quando fa il 3° mi va in IOException perchè dice che il file è in uso da un altro processo!!!

E' assurda come cosa!! anche perchè se lo faccio a mano oppure faccio ma MOVE da dos funziona correttamente!!

cosa mi può impegnare il processo?

grazie
ciao
Fabio

0v3rCl0ck Profilo | Guru

>Ciao a tutti,

Ciao

>ho un application service che man mano che elabora i file li
>sposta in una cartella di archivio.
>
>tutti i file si trovano in un unica directory e sono accumunati
>per gruppo dalla substring delle prima 2 lettere del file
>
>i file sono 8 per ogni gruppo e i gruppi 6
>
>finita l'elaborazione di ogni gruppo mi sposto gli 8 file :
>
>la cosa assurda è che per ogni gruppo mi sposta solo 2 file quando
>fa il 3° mi va in IOException perchè dice che il file è in uso
>da un altro processo!!!
>
>E' assurda come cosa!! anche perchè se lo faccio a mano oppure
>faccio ma MOVE da dos funziona correttamente!!
>
>cosa mi può impegnare il processo?

Hai mai aperto i file? Se si, sei sicuro di averli sempre chiusi (potresti farti aiutare dal costrutto using).

Per vedere chi ti sta tenendo impegnato il file puoi utilizzare un comodo tool fornito ora da microsoft (Process Explorer), che controlla tutti gli handle in windows e da chi sono impegnati:

http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx

>
>grazie
>ciao
>Fabio

Enjoy It
-------------------------------------------------------------------
Michael Denny
Senior Software Developer - Microsoft Framework (C# ASP.NET VB.NET)
http://blogs.dotnethell.it/Regulator/

kintaro Profilo | Junior Member

ciao
Process Explorer v11.3 già l'avevo ma non ho trovato nulla che mi dice che mi impegna i file

il processo che gira fa una pre elaborazione prima di mettere in macchina i file.
i file non vengono mai aperti.
effettuo un controllo sul numero dei file li sposto nei vari server di produzione e poi li archivio.

la cosa strana è che sempre il 3° file di ogni gruppo che mi da qst errore... anche invertendo l'ordine dei file modificando i nomi sempre il 3° viene catturato dal catch.

siccome non sono ferrato ancora con il .net come posso controllare il processo se è già in uso con la using?

0v3rCl0ck Profilo | Guru

>ciao
>Process Explorer v11.3 già l'avevo ma non ho trovato nulla che
>mi dice che mi impegna i file
>
>il processo che gira fa una pre elaborazione prima di mettere
>in macchina i file.
>i file non vengono mai aperti.
>effettuo un controllo sul numero dei file li sposto nei vari
>server di produzione e poi li archivio.
>
>la cosa strana è che sempre il 3° file di ogni gruppo che mi
>da qst errore... anche invertendo l'ordine dei file modificando
>i nomi sempre il 3° viene catturato dal catch.
>
>siccome non sono ferrato ancora con il .net come posso controllare
>il processo se è già in uso con la using?

La using è un costrutto che ti aiuta lui ad eseguire il dispose degli oggetti in generale, e nel tuo caso potrebbe farti comodo se usi uno stream.

using (var myStream = new FileStream(@"C:\blabla.txt"))
{
} // se per qualsiasi motivo si esce dal costrutto using, .net ti assicura che verrà lanciato il dispose su myStream, che a suo volta lancierà il .close perchè così sviluppato da ms.

Ma questo solo se aprivi il file. Se non apri il file non capisco come mai ti tenga la risorsa impegnata durante la pre-elaborazione se esegui solo dei copy o move.

Prova a farmi vedere esattamente che metodi sui file esegui durante la pre-elaborazione e successivamente nella post-elaborazione, che controllo al loro interno come funzionano.

Ciao
-------------------------------------------------------------------
Michael Denny
Senior Software Developer - Microsoft Framework (C# ASP.NET VB.NET)
http://blogs.dotnethell.it/Regulator/

kintaro Profilo | Junior Member

I file vengono impegnati solo quando vengono inseriti in un file ZIP (SharpZipLib)
i metodi usati sono come qll dell'esempio che si scarica dall'articolo del sito

poi poi lavoro con gli ZIP per l'elaborazione, che attraverso un opportuno tracciato record inserisco i miei record in tb SQL server

i file restano li fermi!

Dopo che mi sono assicurato che tutte le FASI della procedura siano andati a buon fine decido di archiviare i file (naturalmente data la sensibilità dei dati faccio un BCK dello ZIP)

la funzione che uso per spostare i file è qll che ho postato ... qll che non capisco è perchè dopo 2 che sposto, il terzo mi dice che è impegnato!!!
qst sempre!!!

ho provato anche a fare il File.Copy ... (con il peggioramento delle performance) ma se poi faccio la file.delete dopo il terzo file ho lo stesso errore!!

dove il framework (vers 2.0) impazzisce??

0v3rCl0ck Profilo | Guru

Escludo che la File.Move, posso centrare, altrimenti vorrebbe dire che c'è qualcosa che non va con il tuo ambiente, perchè .net utilizza una funzione kernel32:

[DllImport("kernel32.dll", CharSet=CharSet.Auto, SetLastError=true)] internal static extern bool MoveFile(string src, string dst);

Rimango con il dubbio su SharpZipLib, anche se guardando velocemente il codice, fa buon uso del costrutto Using e quindi in quei punti non dovrebbe esserci problema. Effettivamente lui richiede un apertura del file in maniera Share.Read, quindi può solo essere letto e non spostato se l'handle fosse attivo. Ad ogni modo mi hai detto che anche con la copy da lo stesso problema e per giunta su questo strano 3° file, indipendentemente da quale esso sia. Però è cmq troppo strano, bisognerebbe analizzare bene il flusso del tuo programma.

Puoi intanto postare, per intero, l'eccezione completa che ti da, magari da li si riesce a capire qualcosa di più. E ancora una volta, riesci a fare tutto questo avendo tutto in debug, così da avere un bel dettaglio nell'eccezione generata.

myfiles come lo ottieni?

-------------------------------------------------------------------
Michael Denny
Senior Software Developer - Microsoft Framework (C# ASP.NET VB.NET)
http://blogs.dotnethell.it/Regulator/

kintaro Profilo | Junior Member

scusa mi sono espresso male!!!
con file.copy funziona ma poi quando faccio file.kill ho il problema del file in uso!

riepilogando:

myfiles lo ottengo
// pathfile e conce lo recupero da XML
myfiles = Directory.GetFiles(PathFile, conce + "*", SearchOption.TopDirectoryOnly);
tra l'altro myfiles è una variabile globale dichiarata string[]

lo zip lo creo così :

{
// operazione per zippare il file mps
nomefileZip = FileZip + "\\" + conce + "_" + DateTime.Now.ToString("yyyyMMdd") + ".ZIP";
ZipOutputStream MyNewZip = new ZipOutputStream(File.Create(nomefileZip));
foreach (string myfile in myfiles) // quindi dall'array dei file lavoro con un file per volta! (myfile)
{
FileStream fileStr = File.OpenRead(myfile);
byte[] valByte = new byte[fileStr.Length];
fileStr.Read(valByte, 0, valByte.Length);
ZipEntry myzipentry = new ZipEntry(Path.GetFileName(myfile));
MyNewZip.PutNextEntry(myzipentry);
MyNewZip.Write(valByte, 0, valByte.Length);
}
MyNewZip.Finish();
MyNewZip.Close();
}

poi effettua i salvataggi con il codice postato all'inizio del tread
dettaglio eccezione

-Data {System.Collections.ListDictionaryInternal} System.Collections.IDictionary {System.Collections.ListDictionaryInternal}
[System.Collections.ListDictionaryInternal] {System.Collections.ListDictionaryInternal} System.Collections.ListDictionaryInternal
Message "Il processo non può accedere al file perché è in uso da un altro processo." string
Source "mscorlib" string
StackTrace " in System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)\r\n in System.IO.__Error.WinIOError()\r\n in System.IO.FileInfo.MoveTo(String destFileName)\r\n in PreparaMpsRoma.Program.Fase4_archiviazioneEbck(String pathFileZip, String PathBck, String PathFile, String PathArchivio) in C:\\Documents and Settings\\casalena\\Documenti\\Visual Studio 2005\\Projects\\PreparaMpsRoma\\PreparaMpsRoma\\Program.cs:riga 206" string
TargetSite {Void WinIOError(Int32, System.String)} System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}

spero possa essere di aiuto per la risoluzione del caso!!
ciao e buon fine settimana per chi la finisce ora :)

ciao

Fabio





0v3rCl0ck Profilo | Guru

>scusa mi sono espresso male!!!
>con file.copy funziona ma poi quando faccio file.kill ho il problema
>del file in uso!

Ah ok, ora mi tornano di più i conti.

>
>riepilogando:
>
>myfiles lo ottengo
>// pathfile e conce lo recupero da XML
>myfiles = Directory.GetFiles(PathFile, conce + "*", SearchOption.TopDirectoryOnly);
>tra l'altro myfiles è una variabile globale dichiarata string[]
>
>lo zip lo creo così :
>
> {
> // operazione per zippare il file mps
>nomefileZip = FileZip + "\\" + conce + "_" + DateTime.Now.ToString("yyyyMMdd")
>+ ".ZIP";
>ZipOutputStream MyNewZip = new ZipOutputStream(File.Create(nomefileZip));
>foreach (string myfile in myfiles) // quindi dall'array dei file
>lavoro con un file per volta! (myfile)
> {
>FileStream fileStr = File.OpenRead(myfile);
>byte[] valByte = new byte[fileStr.Length];
>fileStr.Read(valByte, 0, valByte.Length);
>ZipEntry myzipentry = new ZipEntry(Path.GetFileName(myfile));
> MyNewZip.PutNextEntry(myzipentry);
>MyNewZip.Write(valByte, 0, valByte.Length);
> }
> MyNewZip.Finish();
> MyNewZip.Close();
> }

Allora vedendo il codice ora ci si accorge di molte più cose. Ad esempio c'è una File.Create lasciata incustodita, o meglio la si lascia in pasto al ZipOutputStream e si prende come presupposto che esso ce la chiuda una volta finito. Però questo File.Create non è quello che mi preoccupa di più, in quanto da documentazione si legge che esegue un apertura del file in Share.None (http://msdn.microsoft.com/en-us/library/d62kzs03.aspx), quindi in teoria neanche con il copy potrebbe funzionare, e da qui ne deduco che evidentemente qualcuno o qualcosa se ne sta occupando e rilascia l'handle correttamente. Mentre vorrei focalizzarmi sulla variabile oggetto "fileStr" che invece da documentazione appunto di default esegue una lettura a file in modalità Share.Read, quindi con il .Copy non ci sarebbero problemi, ma giustamente quando si va a cancellare il file, quest'ultima operazione da errore; questo però solo se l'handle non è stato rimosso, e secondo me è proprio il nostro caso.

Ti consiglio di utilizzare il costrutto using, anche su quel File.Create, non costa nulla, e almeno sei sicuro che in quello scope i tuoi FileStream sono al sicuro da handle abbandonati.

Ecco come riscriverei quel frammento di codice:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

>
>spero possa essere di aiuto per la risoluzione del caso!!
>ciao e buon fine settimana per chi la finisce ora :)

Prova a vedere come ti ho suggerito e vediamo se persiste il problema. Intanto sicuramente quella parte di codice dovrebbe essere già agevolata dalle using, che per te lanciano il dispose sui FileStream, che a sua volta lancia poi anche la .Close e tutto questo in maniera silente

>
>ciao
>
>Fabio

Ciaooo
-------------------------------------------------------------------
Michael Denny
Senior Software Developer - Microsoft Framework (C# ASP.NET VB.NET)
http://blogs.dotnethell.it/Regulator/

kintaro Profilo | Junior Member

GRAZIE!!!
Funziona tutto perfettamente!!

Non so che lavoro tu faccia, ma credo che una persona che risolva i problemi in grande stile, venga ampiamente ricompensata!!!

grazie davvero tante!!!

ciao
Fabio

0v3rCl0ck Profilo | Guru

>GRAZIE!!!
>Funziona tutto perfettamente!!

Benissimo, sono contento

>
>Non so che lavoro tu faccia, ma credo che una persona che risolva
>i problemi in grande stile, venga ampiamente ricompensata!!!

Grazie

>
>grazie davvero tante!!!

Di niente, anzi sono sempre contento di trovare persone che si applicano e vogliono anche loro attuare eleganti soluzioni.

>
>ciao
>Fabio

Alla prossima
Ciao

-------------------------------------------------------------------
Michael Denny
Senior Software Developer - Microsoft Framework (C# ASP.NET VB.NET)
http://blogs.dotnethell.it/Regulator/
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5