I am running a separate process that minimizes a folder of javascript files. This process creates a new file for each of the js files with "_min.js" appended to it. The next step is to delete the old js files (the ones without "_min.js"). For some reason File.Delete cannot delete these files.
It would appear that some process still has a handle on these files. I get a System.UnauthorizedAccessException exception when I attempt the delete. I have sufficient privileges to this folder. Can someone tell me what I am overlooking?
I am running the process several times in this loop.
foreach (var fileInfo in jsFiles)
{
var outFileName = fileInfo.FullName.Replace(".js", "_min.js");
var compressorPath = "\"C:\\Dev\\Team Interactive Tools\\trunk\\Infrastructure\\MsBuild\\lib\\yuicompressor-2.4.2.jar\"";
StringBuilder stringBuilder = new StringBuilder("-jar " + compressorPath + " ");
stringBuilder.Append("\"" + fileInfo.FullName + "\"");
stringBuilder.Append(" -o " + "\"" + outFileName + "\"");
Process p = new Process();
p.StartInfo.FileName = "\"C:\\Program Files (x86)\\Java\\jre6\\bin\\java\"";
p.StartInfo.Arguments = stringBuilder.ToString();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
}
return true;
}
Then I try to remove the orginals:
private void RemoveOrginalJs(FileInfo[] files)
{
foreach (var fileInfo in files)
{
File.Delete(fileInfo.FullName);
}
}
I am tried Process.close() after each process run but it makes no differance.
I don't know the tool that you are starting, but waiting for its completion somehow seems the right thing to do:
p.Start();
p.WaitForExit();
Maybe the threads still have the file locked? Do you wait for them to finish before you try and delete?
Try Process.Kill() and delete afterwards.
Further you have to check if the script isn't running in another process aswell. To determinate this, try using Unlocker.
Related
I am working with voice records. I need to use an .exe file for convert Wav to .mp3 file. Everything is fine I can execute this exe but I need to do something after when process end with my output .mp3 file. I know my output directory but i cant handle MP3 file before its not created yet. I know maybe I need to use Thread.sleep(); or something like that because I cant catch a file before its not exist.
Here is my code:
string mp3GuidName = Guid.NewGuid().ToString();
var mp3FilePath = WavFilePath.Replace("finalWavFile", mp3GuidName).Replace("wav", "mp3");
var extrasFilePath = HttpContext.Current.Server.MapPath("/").Replace("DevApp.Web", "Extras");
string strArguments = "/c start " + extrasFilePath + "lame.exe --abr 80 -V5 " + WavFilePath + " " + mp3FilePath;
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = false;
startInfo.UseShellExecute = false;
startInfo.FileName = "cmd.exe";
startInfo.Arguments = strArguments ;
process.StartInfo = startInfo;
process.Start();
var attactment = new Attachment
{
CreatedOn = DateTime.Now,
UpdatedOn = DateTime.Now,
Title = mp3GuidName +".mp3",
Size = _storageProvider.GetFile(mp3FilePath).GetSize(), // here I am trying to get mp3 file but i cant catch it. Because if this wav files size is huge, then convert process is taking time and my mp3 file is not created yet.
FileExtension = _storageProvider.GetFile(mp3FilePath).GetFileType()
};
attactment.MimeType = _storageProvider.GetMimeType(attactment.FileExtension);
attactment.FileUrl = mp3GuidName+".mp3";// file.GetName();
attactment.AttachmentFolderId = folder.Id;
_attachmentRepository.Add(attactment);
I was try to use process.WaitForExit();but I cant solve this problem. I still cant acces to mp3 file.
so how can I catch when the process finish?
Best Regards.
Remove the start command argument from your argument string and you should be able to use process.WaitForExit(); to wait for Lame to finish with encoding:
string strArguments = "/c " + extrasFilePath + "lame.exe --abr 80 -V5 " + WavFilePath + " " + mp3FilePath;
However, you can simplify your code and avoid this dance with cmd.exe altogether by starting lame.exe directly:
string strArguments = "--abr 80 -V5 " + WavFilePath + " " + mp3FilePath;
...
startInfo.FileName = extrasFilePath + "lame.exe";
startInfo.Arguments = strArguments;
...
Below some information about why using the start command argument in your scenario is counterproductive.
Executing console applications such as lame.exe using cmd.exe (or from a console or batch file) normally block cmd.exe (or console/batch file) until the console application exits.
However, using the start command turns this normally blocking execution of a console application into a non-blocking execution. With this argument, the cmd.exe (or console/batch file) will continue execution while the console application is still running. In your particular case it means cmd.exe will exit right after it has started lame.exe (since it has nothing else to execute), effectively sabotaging your attempt to wait for lame.exe to finish.
Edited:
Base on the comments below I have to make it clear that the oroginal solution I recommended does not check if the file is free but it checks only if the file exists!
So I rather recommend the following:
private bool IsBusy(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.None);
}
catch ()
{
return true;
}
finally
{
if (stream != null)
stream.Close();
}
return false;
}
the usage will be:
while(IsBusy(fileinfo))
{
//just wait
}
ORIGINAL:
You can use a while loop to find out when the file is ready:
while(!File.Exists(mp3FileName))
{
//just wait
}
// add the attachment here
I'm new to c# as well as this website so I'll probably make some mistakes but hopefully I'll learn as well.
I'm trying to develop an app to extract from a .7z a file, read it and delete it before moving to the next (there is about 12k files in there, which take up a lot of space).
Now, I'm using .NET 2.0 and I haven't found easy solutions to extract single files from an archive. I came across a post explaining that you could use 7za.exe to do so from the command line, and so I did. Now, the problem is that if I try to do the same in my app 7za throws the "cannot use absolute pathnames" error. However, as I said, the same parameters work at the command prompt.
My idea is to get a list of all the files in the compressed folder and put it in a textfile. From there it is as easy as get the name of the first one, unzip it, read it, delete it and move to next. This is what I got to get the list:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = #"C:\Users\yadayada\Desktop\7za.exe"; //just testing
string parameters= "-y l " + path_file7z + " > " + path_file_destination + #"\file.txt";
//needeless to say, path_file7z and path_file_destination are strings with the correct path like "C:\Users\yadayada\Desktop"
startInfo.Arguments = parameters
process.StartInfo = startInfo;
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
As I said, as the process ends I can see a console opening and closing. I took a screenshot to check what it said and the error I got was the one I said at the begining of the question.
Now, does anyone know why I get this error and how can I fix this?
SOLUTION
Ended un going for a not too elegant (being gentle) solution that works.
To list the names:
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.FileName = #"cmd.exe";
string parameters= "/k -y l " + path_file7z + " > " + path_file_destination + #"\file.txt";
//needeless to say, path_file7z and path_file_destination are strings with the correct path like "C:\Users\yadayada\..."
startInfo.Arguments = parameters
process.StartInfo = startInfo;
process.StartInfo.UseShellExecute = false;
process.Start();
Thread.Sleep(1000);
process.Kill();
Now, once this has been done the extract part is tanken care of by a method similar to the one provided by Igor's links:
public void ExtractFile(string source, string element, string destination)
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.FileName = /*7zG.exe's path*/;
startInfo.Arguments = #"-y x " + source + " -o" + destination + " " + element + " -r";
process.StartInfo = startInfo;
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
}
I think it is working well now. If I have further issues I'll update this with the solutions I come up with with the help provided. Thanks again!
Use this tutorial for 7zip:
https://stick2basic.wordpress.com/2013/04/25/how-to-extract-7z-file-to-a-folder-c-net/
Use this library if rar and zip are allowed:
http://dotnetzip.codeplex.com/
private void MyExtract()
{
string zipToUnpack = "C1P3SML.zip";
string unpackDirectory = "Extracted Files";
using (ZipFile zip1 = ZipFile.Read(zipToUnpack))
{
// here, we extract every entry, but we could extract conditionally
// based on entry name, size, date, checkbox status, etc.
foreach (ZipEntry e in zip1)
{
e.Extract(unpackDirectory, ExtractExistingFileAction.OverwriteSilently);
}
}
}
EDIT
This can help you:
Unzip a file in c# using 7z.exe
Happy to help you!
I have an application that dumps a lot of files to a directory. I want to copy these files to a Hadoop cluster using the hadoop command. I use the following code to run the command.
System.Diagnostics.ProcessStartInfo export = new System.Diagnostics.ProcessStartInfo();
export.RedirectStandardOutput = false;
export.RedirectStandardError = false;
export.UseShellExecute = false;
export.WorkingDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
export.FileName = "hadoop";
export.Arguments = "fs -copyFromLocal " + Path.Combine(dumpDirectory, "*.txt") + " " + hadoopPath));
Console.WriteLine("Copying data: hadoop " + export.Arguments);
System.Diagnostics.Process proc = System.Diagnostics.Process.Start(export);
proc.WaitForExit();
if (proc.ExitCode == 0)
{
IEnumerable<string> files = Directory.EnumerateFiles(dumpDirectory);
foreach (string file in files)
File.Delete(file);
}
else
Console.WriteLine("Error copying to Hadoop: " + proc.ExitCode);
The program writes the following message:
Copying data: hadoop fs -copyFromLocal local/directory/*.txt /user/remote/directory/
copyFromLocal: `local/directory/*.txt': No such file or directory
Error copying to Hadoop: 1
Interestingly, when I run the command manually, the files copy without error.
Also, if the program runs the command without using *.txt and instead calls the command for each file individually, the command succeeds.
Can anyone shed some light on this?
I partially resolved the problem by creating a bash script containing the given command. I ran the bash script programmatically and it worked.
However, I still do not know why the original did not work.
I am trying to run a process called "prog.exe" with the arguments "blah $00" (sort of a code) but whatever I try fails.
string file = "blah $00";
string result = string.Empty;
ProcessStartInfo P = new ProcessStartInfo(#"""" + "prog.exe" + #"""");
P.Arguments = #"""" + file + #"""";
P.CreateNoWindow = true;
P.UseShellExecute = false;
P.RedirectStandardOutput = true;
Process.Start(P);
using (Process process = Process.Start(P))
{
using (StreamReader str = process.StandardOutput)
result = str.ReadToEnd();
}
MessageBox.Show(result);
When this code is executed, my program just crashes and I am forced to close it using the Task Manager.
I am not sure what's wrong with my code (am I not setting the arguments correctly?), so any help would be appreciated.
Run your process with given argument from console and see what happens. If result is something you expect, just remove double quotes and this should resolve your problem.
I don't think your program crashes. It just waits for "prog.exe" to finish! I bet, that your program continues running as soon as you are done working with prog.exe and close it - and make sure in task manager that it really is gone.
My website runs a local .exe file (generates some data), when a user clicks a certain link.
I would like to know how to do the following
what command to use to run the .exe?
where should I store the .exe and still maintain security?
I use .net 4 c#
Not sure if this works in MVC, but give it a shot:
// Process class resides in System.Diagnostics namespace
Process myProcess = Process.Start("...");
myProcess.WaitForExit();
// todo : process your data
Here's something that I use in one of my applications:
var p = new Process();
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.FileName = HttpContext.Current.Server.MapFfmpegPath();
p.StartInfo.Arguments = "arguments go here :)";
p.Start();
p.WaitForExit();
As for the executable itself, I created a directory in my project and put the exe in that directory. The MapFfmpegPath method looks something like this.
public static string MapFfmpegPath(this HttpServerUtility server)
{
return "\"" + server.MapPath("/CoolPathHere/ffmpeg.exe") + "\"";
}