मेरे पास C#.NET 3.5 में विकसित क्लाइंट-सर्वर एप्लिकेशन है। यह एप्लिकेशन आवश्यक कार्य को पूरा करने के लिए 3 कार्यक्रमों का उपयोग करता है। प्रोसेस ए (सर्वर) और प्रोसेस बी (रिमोट लॉन्चर) को .NET में विकसित किया गया है और प्रोसेस सी एक थर्ड पार्टी कंसोल एप्लिकेशन है जिसकी विकास भाषा ज्ञात नहीं है। रिमोट कंप्यूटर के एडमिनिस्ट्रेटिव क्रेडेंशियल्स का उपयोग करते हुए, प्रोसेस ए उस पर प्रोसेस बी को कॉपी करता है और प्रोसेस बी को रिमोट कंप्यूटर पर टास्क के रूप में शेड्यूल करता है। इसके बाद, प्रोसेस बी टास्क शेड्यूलर द्वारा शुरू होता है और यह संदेशों को लॉग करने के लिए log.txt फाइल बनाता है। फिर प्रोसेस बी Process.Start() सेमेन्टिक्स का उपयोग करके प्रोसेस सी शुरू करता है और इसके standard output and error को log.txt फाइल में लिखने के लिए रीडायरेक्ट करता है। प्रक्रिया A, दूरस्थ कंप्यूटर पर प्रक्रिया C अभी भी चल रहा है या नहीं, इसकी निगरानी के लिए Process.GetProcesses(remotecomputername) शब्दार्थ का उपयोग करता है। प्रक्रिया A log.txt फ़ाइल को \\RemoteComputerName\C$\RemoteDir\log.txt की तरह पढ़े गए नेटवर्क शेयर का उपयोग करके भी पढ़ रही है और इसकी विंडो पर संदेश प्रदर्शित कर रही है।

मेरी समस्या यह है कि log.txt पर सभी आउटपुट और त्रुटि लॉग नहीं हो रही हैं। और प्रक्रिया A log.txt से सही ढंग से पढ़ने में सक्षम नहीं है। यदि डीबग व्यू का उपयोग करके आउटपुट/त्रुटि लॉग की गई है तो वे सही तरीके से लॉग हो रहे हैं। क्या यह सिंक्रनाइज़ेशन/एक्सेस अधिकार समस्या है? मैं इससे छुटकारा कैसे पाऊं? कोई संकेत/संकेत वास्तव में मूल्यवान होगा। प्रतिबंधों के कारण पूरा कोड साझा करने में असमर्थ।

नमूना कोड नीचे दिया गया है

प्रक्रिया ए

//Below method is called every 2 seconds from Server to read new messages.
//path passed as `\\RemoteComputerName\C$\RemoteDir\log.txt`
private void ReadRemoteLog(string path)
{
    try
    {
        string[] lines = File.ReadAllLines(path);
        while (RemoteLogPosition < lines.LongLength)
        {
            string msg = lines[RemoteLogPosition].Trim();
            if (!string.IsNullOrEmpty(msg))
            {
                Trace.WriteLine("# " +msg); //Writing on DebugView
                OnProgressChanged(msg);
            }
            RemoteLogPosition++; //This is global variable to keep track of last read position.
        }      
    }   
}

प्रक्रिया सी शुरू करने के लिए प्रक्रिया बी का कोड

ProcessStartInfo ps = new ProcessStartInfo();
ps.UseShellExecute = false;
ps.FileName = <Path to process C>;
ps.Arguments = <Commandline args to Process C>;
ps.WorkingDirectory = @"C:\RemoteDir";
ps.RedirectStandardError = true;
ps.RedirectStandardOutput = true;

Process p = new Process();
p.StartInfo = ps;

p.OutputDataReceived += (s, e) => { WriteLog(e.Data.Trim());};
p.ErrorDataReceived += (s, e) => { WriteLog(e.Data.Trim()); };
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();
WriteLog("Process Started - "+ps.FileName + ps.Arguments);
p.WaitForExit();

प्रक्रिया बी की राइटलॉग विधि -

private void WriteLog(string message)
{
    using (FileStream fs = new FileStream(@"C:\\RemoteDir\log.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Inheritable))
    using(StreamWriter sw = new StreamWriter(fs))
    {
        sw.WriteLine("#" + message);
    }
}
1
Omkar 5 सितंबर 2018, 11:38
ऊंच-नीच से गैर-उन्नत प्रक्रिया शुरू करने के लिए क्या आप किसी भी बिंदु पर प्रयास करते हैं?
 – 
anefeletos
10 सितंबर 2018, 21:04
जब आप कहते हैं मेरी समस्या है, सभी आउटपुट और त्रुटि log.txt पर लॉग नहीं हो रहे हैं। क्या आपका मतलब है कि उनमें से केवल कुछ ही लॉग होते हैं, लेकिन सभी नहीं? मेरे पास यह मुद्दा एक बार था जहां आउटपुट इतना अधिक था कि फ़ाइल पिछले लेखन से लॉक हो जाएगी ताकि लॉग का हिस्सा गायब हो जाए। मुझे public static void Log(string message) { using (StreamWriter w = File.AppendText("logfiles.txt")) { w.WriteLine(message); } } के साथ सफलता मिली है
 – 
AsheraH
12 सितंबर 2018, 11:33
- ठीक कह रहे हैं आप। कुछ लॉगिंग स्टेटमेंट गायब हैं। पहले मैंने आपके समाधान की कोशिश की लेकिन उम्मीद के मुताबिक काम नहीं किया। मुझे इसे एक बार और आजमाना होगा। जल्द ही परिणाम अपडेट करेंगे।
 – 
Omkar
13 सितंबर 2018, 13:01

3 जवाब

याद रखें कि फाइल लिखे जाने पर उसे एक्सक्लूसिव लॉक मिलता है। तो यदि दो धागे एक ही समय में लिख रहे हैं तो उनमें से एक अपवाद में आ जाएगा। पढ़ना कोई समस्या नहीं है। आसान समाधान एकाधिक लॉग फ़ाइल बनाना या डेटाबेस का उपयोग करना है। दूसरा तरीका यह है कि संदेश जमा करते रहें और एक घंटे में एक बार लिखें या जब संदेश 100 तक हो। स्ट्रिंग की सूची बनाएं

List<string> messagelst= new List<string>();
private void WriteLog(string message)
{


        messagelst.Add("New York");
        messagelst.Add("Mumbai");
        messagelst.Add("Berlin");
        messagelst.Add("Istanbul");
if(messagelst.length==100){
string message= string.Join(",", messagelst.ToArray());

    using (FileStream fs = new FileStream(@"C:\\RemoteDir\log.txt", FileMode.OpenOrCreate, FileAccess.Write, FileShare.Inheritable))
    using(StreamWriter sw = new StreamWriter(fs))
    {
        sw.WriteLine("#" + message);
    }

messagelst= new List<string>();

}
}

दूसरा तरीका है async लिखना। आप अनुक्रम खो सकते हैं।

static Task ProcessWrite()
{
    string filePath = @"c:\temp2\temp2.txt";
    string text = "Hello World\r\n";

    return WriteTextAsync(filePath, text);
}

static async Task WriteTextAsync(string filePath, string text)
{
    byte[] encodedText = Encoding.Unicode.GetBytes(text);

    using (FileStream sourceStream = new FileStream(filePath,
        FileMode.Append, FileAccess.Write, FileShare.None,
        bufferSize: 4096, useAsync: true))
    {
        await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
    };
}
1
Jin Thakur 13 सितंबर 2018, 22:22

संक्षिप्त उत्तर: File.ReadAllLines दूसरी प्रक्रिया को फ़ाइल में लिखने नहीं देगा। संबंधित SO प्रश्न जिसमें कुछ कामकाज हैं: File.ReadLines को बिना लॉक किए?

तथ्य यह है कि ReadAllLines FileShare.Read के साथ फ़ाइल खोल रहा है, .Net संदर्भ स्रोत कोड को देखकर पाया जा सकता है: https://referencesource.microsoft.com/#mscorlib/system/ io/file.cs,5150c565446cd5fd

कॉल्स को ट्रेस करके, यह अंततः पहुंचेगा:

Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read, DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false, checkHost);

FileShare.Read कहता है

फ़ाइल को बाद में पढ़ने के लिए खोलने की अनुमति देता है। यदि यह ध्वज निर्दिष्ट नहीं है, तो फ़ाइल को पढ़ने के लिए खोलने का कोई भी अनुरोध (इस प्रक्रिया या किसी अन्य प्रक्रिया द्वारा) फ़ाइल बंद होने तक विफल हो जाएगा।

भले ही ReadAllLines फ़ाइल को बंद कर देगा, पढ़ने की प्रक्रिया के दौरान, फ़ाइल अन्य प्रक्रिया को लिखने के लिए उपलब्ध नहीं है।

दूसरी प्रक्रिया (आपकी प्रक्रिया सी) को इस फ़ाइल को लिखना जारी रखने की अनुमति देने के लिए आपको अनिवार्य रूप से, FileShare.ReadWrite (आपकी प्रक्रिया ए में) के साथ फ़ाइल खोलने की आवश्यकता है।

1
Subbu 14 सितंबर 2018, 20:36

फ़ाइल में लिखते समय आप किसी ऑब्जेक्ट को लॉक के रूप में उपयोग करने का प्रयास कर सकते हैं:

private static object fileLock = new Object();

अब आपकी WriteLog विधि में: आप lock(fileLock) {} का उपयोग करके स्ट्रीम को डिस्पोज़ करने के लिए उपयोग कर सकते हैं।

साथ ही आप EventWaitHandle. यह प्रत्येक प्रक्रिया के लिए प्रतीक्षा हैंडल का एक उदाहरण बनाने की अनुमति देता है।

var wait = new EventWaitHandle(true, EventResetMode.AutoReset, "Common_to_all_process");

फिर पहली प्रक्रिया समाप्त होने के बाद, यह इसे अगली प्रक्रिया को संकेत देकर भेज सकता है:

wait.WaitOne();
/* write to the file*/
wait.Set();

"Common_to_all_process" के लिए कोई GUID का उपयोग कर सकता है।

0
Gauravsa 15 सितंबर 2018, 10:27