I need help with C#, the question is how can I check if a .txt file exists in a folder using the timer counter, if the file already exists the counter will be stopped and attached. the message that the file is available, i ask the timer to check the folder continuously if the file already exists, the timer will stop, thanks
I hope someone will help
That is my solution to your question.
DateTime DT_Start = DateTime.UtcNow;
bool FileIsFound = false;
const int ONESEC = 1000;
string Path = #"C:\Users\Schecher_1\Desktop";
string FileName = "test.txt";
while (!FileIsFound)
{
FileIsFound = Directory.EnumerateFiles(Path, FileName).Any();
Thread.Sleep(ONESEC);
}
Console.WriteLine($"The File {FileName} was found! " +
$"{Environment.NewLine}" +
$"{(DT_Start - DateTime.UtcNow).ToString("hh':'mm':'ss")} were needed!");
var isFileExists = false;
while (!isFileExists)
{
isFileExists = Directory.EnumerateFiles("directoryToSearch", "*.txt").Any();
Thread.Sleep(1000);
}
Console.WriteLine("File found!");
Related
I need to copy a bunch of files from an Android phone to the PC.
It doesn't work the normal way, the PC is super slow and crashes all the time for some reason.
I want to copy it file by file.
My problem is that if I use Directory.GetFiles("Path") or DirectoryInfo.GetFiles("Path") it does add the persistant Datapath to the path for some reason and I get this error message:
DirectoryNotFoundException: Could not find a part of the path 'D:\GameDev\CopyProgram\Dieser PC\HTC One M9\Interner gemeinsamer Speicher'.
The actual path is only "Dieser PC\HTC One M9\Interner gemeinsamer Speicher", is there any way to do that?
//there is an input field where you can enter the paths
(copy it from the explorer)
[SerializeField]
private string copyFrom = "Dieser PC\HTC One M9\Interner gemeinsamer Speicher";
[SerializeField]
private string copyTo = "C:\Users\Nutzer\Desktop\Neuer Ordner";
private bool running = false;
public void Copy()
{
if(running == true)
{
return;
}
running = true;
//Start
//Get all items from folder
DirectoryInfo d = new DirectoryInfo(copyFrom);
FileInfo[] Files = d.GetFiles();
foreach (FileInfo file in Files)
{
string currentFile = file.DirectoryName + "/" + file.Name;
string copyFile = copyTo + "/" + file.Name;
try
{
if (file == null)
continue;
File.Copy(currentFile, copyFile, true);
}
catch (Exception)
{
throw;
}
}
//End
running = false;
}
I searched through the internet and could not find a solution, please help!
Thanks!
I've written a set of web services using Web Api 2. They eventually end up calling a CMD program that fires up a OpenEdge Progress client, passes a formatted XML string and then inserts records into a OpenEdge Progress database by calling a .p procedure (WebSpeed is not an option).
The .P file has a set of business logic to run against a Progress application. It subsequently generates an XML file on completion containing an < Error > node. If this node is empty - then it worked. If the file doesn't exist or the node contains text... it failed. I then read this XML file and pass the contents of the < Error > node back to the client in Web Api.
At the moment, there is a static delay of 10 seconds from calling the CMD/Progress applet, to attempting to read the XML file, to give the server time to run the .P file and create said XML file. This isn't great, though, and occasionally an error is returned to the client because it can't find the file, yet, the file was created 1 second after the response was returned because of abnormally high server loads. Alternatively, people are forced to wait 10 seconds when the response could have been handled in 2 seconds.
I need to come up with a way to "check until file exists" until a timeout period has elapsed. I've done some research and can't find anything suitable for a Web Api environment. Does anyone have any suggestions?
Code below - forgive me. I've very much been learning as I've been going along and am very new to this!
Controller
// the request date/time
DateTime requestDate = DateTime.Now;
// list of validation errors
List<string> ohValidation = new List<string>();
...
WebExtensions.callInsertProgram(xml, "JOBLOG");
ohValidation = XmlExtensions.ReadProgressXmlFileWithArray(job.logjob.placeref, requestDate, "joblogging");
CallInsertProgram
public static void callInsertProgram(string xml, string program)
{
try
{
using (Process p = new Process())
{
p.StartInfo.FileName = #"C:\Rubixx\runProgress.exe";
p.StartInfo.WorkingDirectory = #"C:\Rubixx";
// stop windows from appearing on the server
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
// set the arguments for running. The program name and xml are passed in as arguments
// wrapped in escaping "\" to stop spaces from being treated as a separator
p.StartInfo.Arguments = "\"" + program + "," + xml + "\"";
p.Start();
}
}
catch (Exception e)
{
throw new OpenHousingException(e.Message.ToString());
}
}
ReadProgressXMLWithArray
public static List<string> ReadProgressXmlFileWithArray(string reference, DateTime requestDateTime, string folder)
{
// new empty list
List<string> output
= new List<string>();
// wait X seconds before doing anything
// to ensure the XML file has time to be created
Delay_Start(fileDelay);
//
string filename = fullFileName(jobno, folder, requestDateTime);
string filepath = getFullFilepath(filename, folder);
if (checkXmlFileExists(filepath))
{
// if so check for the existence of an error message
output = getXmlErrorArray(filepath);
}
else
{
// if no file is found - the call to Progress hasn't executed. So tell the end user.
throw new OpenHousingException("No OpenHousing file could be found");
}
return output;
}
Delay_Start
private static void Delay_Start(int Seconds)
{
DateTime StartTime;
DateTime EndTime;
StartTime = DateTime.Now;
EndTime = StartTime.AddSeconds(Seconds);
do
{ StartTime = DateTime.Now; } while (StartTime < EndTime);
}
FullFileName (needed because I can't be sure of XML filename until created. File Format is UniqueReference_DateTimeFileCreated.xml (xxxxxxxx_20160401-1100.xml) So, I have to wildcard search a folder with a unique reference).
public static string fullFileName(string jobNo, string folder, DateTime createdDate)
{
string fileName = string.Empty;
string folderPath = fileLocation + folder;
DirectoryInfo dir = new DirectoryInfo(folderPath);
FileInfo[] files = dir.GetFiles(jobNo + "*", SearchOption.TopDirectoryOnly).Where(f => f.CreationTimeUtc > createdDate || f.LastWriteTimeUtc > createdDate).ToArray() ;
foreach (var item in files)
{
fileName = item.Name;
}
if (string.IsNullOrEmpty(fileName))
throw new OpenHousingException("No OpenHousing file could be found");
return fileName;
}
GetFullFilePath (Can probably be consolidated into fullFileName)
private static string getFullFilepath(string filename, string folder)
{
return fileLocation + folder + #"\" + filename;
}
CheckXMLFileExists
private static bool checkXmlFileExists(string filepath)
{
bool fileExists = false;
if (File.Exists(filepath))
{
fileExists = true;
}
return fileExists;
}
GetXMLErrorArray
private static List<string> getXmlErrorArray(string filepath)
{
List<string> output
= new List<string>();
// read the text from XML file
using (TextReader txtReader = new StreamReader(filepath))
{
XmlSerializer xs
= new XmlSerializer(typeof(JobError));
// de-serialise the xml text
// to a strongly typed object
JobError result = (JobError)xs.Deserialize(txtReader);
// if the xml file contains an error - return it to the client
if (!string.IsNullOrEmpty(result.ErrorText))
output.Add(result.ErrorText);
//check for SoR errors that are created under a different node
if (result.LineError != null)
{
List<LineError> lineErrs = result.LineError.ToList();
foreach (LineError le in lineErrs)
{
output.Add(le.SorCode + ":" + le.Error);
}
}
}
return output;
}
OK - so I think I was overcomplicating the problem.
Instead of waiting for the file to exist, I added a line into my CallInsertProgram method as below (as suggested by RB...
public static void callInsertProgram(string xml, string program)
{
try
{
using (Process p = new Process())
{
p.StartInfo.FileName = #"C:\Rubixx\runProgress.exe";
p.StartInfo.WorkingDirectory = #"C:\Rubixx";
// stop windows from appearing on the server
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = true;
// set the arguments for running. The program name and xml are passed in as arguments
// wrapped in escaping "\" to stop spaces from being treated as a separator
p.StartInfo.Arguments = "\"" + program + "," + xml + "\"";
p.Start();
// ADDED
p.WaitForExit(60000);
}
}
catch (Exception e)
{
throw new OpenHousingException(e.Message.ToString());
}
}
This ensures that the Progress cmd applet is completed before moving onto the next line - at which point the XML will have been created (or not if it's failed). Initial testing is working well. Can anyone foresee any problems with this approach?
So, I have a simple screen that registers the saves made in various text files (this is what I call "escenario". I can haveseveral escenarios for the important changes made to the files, and later on, if I want to return to a past escenario, I just load the files I saved. That works great, but my problem is when I try to start the process of the .exe for the python code that makes the copies of the files.
protected void AddItem(object sender, EventArgs e)
{
int num = 0;
int totalItems = escenario_list.Items.Count;
if (totalItems > 0){
string esc = "Escenario ";
num = totalItems + 1;
var x = esc + num.ToString();
var date = DateTime.Now.ToString();
var str = x + " - " + date;
escenario_list.Items.Add(new ListItem(str, num.ToString()));
Process.Start(#"C:\inetpub\wwwroot\AdministracionEscenarios\bin\MoveFiles\MoveFiles.exe");
}
else if(totalItems == 0){
string esc = "Escenario ";
num = 1;
var x = esc + num.ToString();
var date = DateTime.Now.ToString();
var str = x + " - " + date;
escenario_list.Items.Add(new ListItem(str, num.ToString()));
Process.Start(#"C:\inetpub\wwwroot\AdministracionEscenarios\bin\MoveFiles\MoveFiles.exe");
}
}
So Process.Start just won't start that .exe file. What can be the reason?? I'm also using using System.Diagnostics; at the beggining, so that's not the issue here. Thanks for the help!
The issue is how you're referencing your local drive on the server. Use this method instead Path.Combine(HostingEnvironment.MapPath("~/bin/MoveFiles/"), "MoveFiles.exe"); The HostingEnvironment will reference the directory on the server. You've been referencing the customer's local directory and not the server's local directory
Also, download and launch process explorer, and go to Find and Find Handle. Run your program and search for the MoveFiles.exe file. This will ensure that your application has executed on the server.
I am writing an application which launches a tester (.cmd), so I am passing in the tests that have been entered into a listbox. This method works perfectly fine if there is one test entered, but if there is 2 or more, it give me the error:
"An unhandled exception of type 'System.ComponentModel.Win32Exception'
occurred in System.dll
Additional information: The system cannot find the file specified"
The StartInfo.Filename and the currentTestFromListbox[i] both look correct in the debugger.
Anyone have any idea where I'm going wrong?
I apologize that my code is confusing--im just a beginner.
public void executeCommandFiles()
{
int i = 0;
int ii = 0;
int numberOfTests = listboxTestsToRun.Items.Count;
executeNextTest:
var CurrentTestFromListbox = listboxTestsToRun.Items.Cast<String>().ToArray();
string filenameMinusCMD = "error reassigning path value";
int fileExtPos = CurrentTestFromListbox[i].LastIndexOf(".");
if (fileExtPos >= 0)
{
filenameMinusCMD = CurrentTestFromListbox[i].Substring(0, fileExtPos);
}
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Arguments = #"pushd Y:\Tests\" + filenameMinusCMD + #"\" + CurrentTestFromListbox[i];
startInfo.WorkingDirectory = #"pushd Y:\Tests\" + filenameMinusCMD + #"\";
startInfo.FileName = CurrentTestFromListbox[i];
Process.Start(startInfo);
//Wait for program to load before selecting main tab
System.Threading.Thread.Sleep(10000);
//Select MainMenu tab by sending a left arrow keypress
SendKeys.Send("{LEFT}");
i++;
if (i < numberOfTests)
{
checkIfTestIsCurrentlyRunning:
foreach (Process clsProcess in Process.GetProcesses())
{
if (clsProcess.ProcessName.Contains("nameOfProgramIAmTesting"))
{
System.Threading.Thread.Sleep(2000);
//if (ii > 150)
if (ii > 6) //test purposes only
{
MessageBox.Show("The current test (" + filenameMinusCMD + ") timed out at 5 minutes. The next test has been started.", "Test timed out",
MessageBoxButtons.OK,
MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1);
}
ii++;
goto checkIfTestIsCurrentlyRunning;
}
goto executeNextTest;
}
}
}
}
Thanks!
-Joel
Here is your code re-factored. The sleeps/gotos were really bothering me. I couldn't really test it, but I think it should work the same. Let me know if it doesn't work or you have any questions.
This assumes your listbox has content like this in it:
testname.cmd
test2.cmd
test3.exe
lasttest.bat
Here is my attempt:
public void executeCommandFiles()
{
foreach (string test in listboxTestsToRun.Items)
{
//gets the directory name from given filename (filename without extension)
//assumes that only the last '.' is for the extension. test.1.cmd => test.1
string testName = test.Substring(0, test.LastIndexOf('.'));
//set up a FileInfo object so we can make sure the test exists gracefully.
FileInfo testFile = new FileInfo(#"Y:\Tests\" + testName + "\\" + test);
//check if it is a valid path
if (testFile.Exists)
{
ProcessStartInfo startInfo = new ProcessStartInfo(testFile.FullName);
//get the Process object so we can wait for it to finish.
Process currentTest = Process.Start(startInfo);
//wait 5 minutes then timeout (5m * 60s * 1000ms)
bool completed = currentTest.WaitForExit(300000);
if (!completed)
MessageBox.Show("test timed out");
//use this if you want to wait for the test to complete (indefinitely)
//currentTest.WaitForExit();
}
else
{
MessageBox.Show("Error: " + testFile.FullName + " was not found.");
}
}
}
I've got a C# windows forms application where I load XML files and CGM graphics files into my application from an Open File browser. I seem to be able to select a couple of hundred at a time and it works without fault, but any more and a dialog box pops up telling me it can't find file such and such, but only gives half the file name. I'm assuming this is due to a limit on the amount of files that can be selected / processed in one go through the open file dialog.
Does anybody know what that number is, and is there a way around it if i have more than that limit to select at once?
I'm effectively 'importing' the files into my application, whereby using a foreach loop the selected files get moved to another folder, and the application writes to an XML file with all the file names of the files imported (as well as other data on the files).
Below is the entire 'import' method
private void addFilesToCSDBToolStripMenuItem_Click(object sender, EventArgs e)
{
int DMsimported = 0;
int graphicsImported = 0;
if (projectName == "")
{
MessageBox.Show("Please open a project first", "DAWS");
return;
}
DialogResult result = openFileDialog1.ShowDialog();
if (result == DialogResult.OK)
{
MessageBox.Show("This process may take several minutes depending on the number of imports", "DAWS");
Application.UseWaitCursor = true;
foreach (string file in openFileDialog1.FileNames)
{
string fileName = Path.GetFileNameWithoutExtension(file); //Gets just the name from the file path
string ext = Path.GetExtension(file.ToLower());
if (ext != ".CGM" && ext != ".cgm")
{
bool exists = xmlFileWriter.checkIfFIleExists(fileName + ext);
if (exists != true)
{
xmlFileWriter.writeDatatoXML(file);
File.Move(file, CSDBpath + projectName + "\\CheckedIN\\" + fileName + ext);
DMsimported = DMsimported + 1;
}
else
{
MessageBox.Show(fileName + " already exists in the CSDB. This file will be skipped.", "DAWS");
}
}
else
{
if (File.Exists(CSDBpath + projectName + "\\Graphics\\" + fileName + ext))
{
if (Properties.Settings.Default.OverwriteGraphics == true)
{
File.SetAttributes(CSDBpath + projectName + "\\Graphics\\" + fileName + ext, FileAttributes.Normal); // need this line in order to set the file attributes. Exception thrown otherwise when system tries to overwrite the file.
File.Delete(CSDBpath + projectName + "\\Graphics\\" + fileName + ext);
File.Copy(file, CSDBpath + projectName + "\\Graphics\\" + fileName + ext); //need to give the option as to whether to delete the existing file or skipp.
}
else
{
MessageBox.Show(fileName + " already exists in the CSDB. This file will be skipped. To enable overwriting tick the checkbox in Preferences", "DAWS");
}
}
else
{
File.Copy(file, CSDBpath + projectName + "\\Graphics\\" + fileName + ext);
}
graphicsImported = graphicsImported + 1;
}
}
Application.UseWaitCursor = false;
buildAllListViews();
copyCGMfilesToDirectories();
if (DMsimported > 0)
{
MessageBox.Show(DMsimported.ToString() + " DM files successfully imported into the CSDB", "DAWS");
}
if (graphicsImported > 0)
{
MessageBox.Show(graphicsImported.ToString() + " graphic files successfully imported into the CSDB", "DAWS");
}
if (graphicsImported == 0 && DMsimported == 0)
{
MessageBox.Show("No files imported", "DAWS");
}
updateMainFilesList();
}
}
According to this article, you will receive a "Too many files selected" error message when you use the OpenFileDialog control to select more than 200 files.
Just tested in .NET 4.5, no problem with 5000 files, so it looks like it depends on .net framework/os version (I've used long enough file names, just to be sure, that it does not depend on some old windows constraint, like max length of all file names is 65536 or 32768):
var directory = #"c:\test\test";
Directory.CreateDirectory(directory);
for (int i = 0; i < 5000; i++)
{
var path = Path.Combine(directory, i.ToString() + new string('a', 200));
File.WriteAllText(path, "");
}
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
var fileCount = openFileDialog1.FileNames;
var lastFileName = openFileDialog1.FileNames[4999];
}
In .NET Framework 1.1, for the OpenFileDialog.Multiselect Property:
There is a hard-coded limit of 200 files that can be opened with the
Open File dialog box. For more information about this limitation, see
article 820631, "PRB: 'Too Many Files Selected' Error Message Occurs
When You Use the OpenFileDialog Control", in the Microsoft Knowledge
Base at http://support.microsoft.com.
When you have to work with such a large number of files, maybe it makes more sense to select only the folder (even more reasonable if you select all the files in the folder, if this is your case). Try using the FolderBrowserDialog Class:
var folderBrowserDialog = new FolderBrowserDialog();
if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
{
var fi = new DirectoryInfo(folderBrowserDialog.SelectedPath);
// here you get the files collection
var files = fi.GetFiles();
}
Try:
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
openFileDialog1.Multiselect = false;
var fileCount = openFileDialog1.FileNames;
var lastFileName = openFileDialog1.FileNames[4999];
}