简体   繁体   中英

C# WriteLine : The process cannot access the file because it is being used by another process

I have a function that read all my files .log inside a folder and extract each error line and later write it in a .csv file. It work with small log files but not with "big file" like >600Ko and return me the error "The process cannot access the file because it is being used by another process."

All my log file a regrouped inside a "logs" folder.

/*
* Extract data from the log file and right it in a conf.csv file
*/
public void DataExtract(string path)
{
    int index = 0;
    int nextLine = 0;
    int descriptionLine = 0;

    string firstLine = "";
    string secondLine = "";
    string description = "";

    try
    {
        if (!String.IsNullOrEmpty(path))
        {
            // Read each line of the file into a string array. Each element
            // of the array is one line of the file.
            string[] logs = System.IO.File.ReadAllLines(path);
            string[] confFile = System.IO.File.ReadAllLines(this.confPath);

            // read each line of the log file
            foreach (string log in logs)
            {
                if (log.Contains("ERROR"))
                {
                    nextLine = index + 1;
                    descriptionLine = index + 2;
                    firstLine = log;
                    secondLine = logs[nextLine];

                    string checkDescr = "";
                    int descNb = descriptionLine + 1;
                    checkDescr = logs[descNb];

                    description = logs[descriptionLine];

                    if (!description.Contains("at"))
                    {
                        descriptionLine++;
                        description = logs[descriptionLine];
                    }

                    if (!confFile.Any(s => s.Contains(firstLine)) || !confFile.Any(s => s.Contains(secondLine)))
                    {
                        using (StreamWriter sw = File.AppendText(this.confPath))
                        {
                            sw.WriteLine(string.Format("{0},{1},{2}", firstLine, secondLine, description));
                        }
                    }

                    index++;
                }

                Console.WriteLine("Done");
            }
        }
        catch (Exception e)
        {
            Console.WriteLine("Problem !");
            Console.WriteLine(e.Message);
        }
    }
}

Then in the Main class i do :

string logPath = directoryPath + "\\logs";
string[] logfiles = Directory.GetFiles(logPath, "*.log");

ErrorRecover errorRecover = new ErrorRecover();

// For each log file call the methode for extracting errors logs
foreach (var file in logfiles)
{
    Console.WriteLine(file);
    errorRecover.DataExtract(file);
}

So according to comments and what I understand I tried to first recover all my logs and store it inside a list and then from the list I write all in my conf.csv file.

I guess it's not the best code ever but it work for now and I don't have the error even with big files.

/*
 * Extract data from the log file and right it in a conf.csv file
 */
public void DataExtract(string path)
{
    
    int index = 0;
    int nextLine = 0;
    int descriptionLine = 0;

    string firstLine="";
    string secondLine="";
    string description="";
    
    var logDatas = new List<string>(); // list who will contain all errors  from all logs files
    string completLog= "";

    try
    {
        
        if (!String.IsNullOrEmpty(path))
        {
            // Read each line of the file into a string array. Each element
            // of the array is one line of the file.
            string[] logs = System.IO.File.ReadAllLines(path);
            string[] confFile = System.IO.File.ReadAllLines(this.confPath);

            // read each line of the log file
            foreach (string log in logs)
            {

                if (log.Contains("ERROR"))
                {
                    nextLine = index + 1;
                    descriptionLine = index + 2;
                    firstLine = log;
                    secondLine = logs[nextLine];
                  

                    string checkDescr="";
                    int descNb = descriptionLine + 1;
                    checkDescr = logs[descNb];

                    description = logs[descriptionLine];
                    if (!description.Contains(" at "))
                    {
                      
                        descriptionLine++;
                        description =  logs[descriptionLine];
                        
                    }
                   
                    completLog = firstLine + "," + secondLine + "," + description;

   
                    logDatas.Add(completLog);

                }

                index++;
            }

            // recover log from the list and write it inside the conn.csv file
            // this logic permit to avoid some error like "The process cannot access the file because it is being used by another process"
            foreach (string log in logDatas)
            {
                if (!confFile.Any(s => s.Contains(firstLine)) || !confFile.Any(s => s.Contains(secondLine)))
                {

                    using (StreamWriter sw = File.AppendText(this.confPath))
                    {

                        sw.WriteLine(log);


                    }

                }

            }
            Console.WriteLine("Done");

        }
    }
    catch (Exception e)
    {
        Console.WriteLine("Problem inside DataExtract method from ErrorRecover");
        Console.WriteLine(e.Message);

    }
}

Get processes who locking file with this method:

static public List<Process> WhoIsLocking(string path)
{
    uint handle;
    string key = Guid.NewGuid().ToString();
    List<Process> processes = new List<Process>();
    int res = RmStartSession(out handle, 0, key);
    if (res != 0) throw new Exception("Could not begin restart session.  Unable to determine file locker.");
    try {
        const int ERROR_MORE_DATA = 234;
        uint pnProcInfoNeeded = 0,
             pnProcInfo = 0,
             lpdwRebootReasons = RmRebootReasonNone;
        string[] resources = new string[] { path }; // Just checking on one resource.
        res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);
        if (res != 0) throw new Exception("Could not register resource.");
        res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);
        if (res == ERROR_MORE_DATA) {
            // Create an array to store the process results
            RM_PROCESS_INFO[] processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
            pnProcInfo = pnProcInfoNeeded;
            res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
            if (res == 0) {
                processes = new List<Process>((int)pnProcInfo);

                // Enumerate all of the results and add them to the 
                // list to be returned
                for (int i = 0; i < pnProcInfo; i++)
                    try {
                        processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
                    }
                    // catch the error -- in case the process is no longer running
                    catch (ArgumentException) { }
            }
            else throw new Exception("Could not list processes locking resource.");
        }
        else if (res != 0) throw new Exception("Could not list processes locking resource. Failed to get size of result.");
    }
    finally
    {
        RmEndSession(handle);
    }
    return processes;
}

then kill that:

List<Process> ps = WhoIsLocking("file path");
foreach(Process p in ps)
    p.Kill();

Done;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM