I am writing a program to function as a testing plugin with a third party program. I have talked with the developer on the other end (don't get me started) and he is using VB 6 to create a batch file and then calls the batch file using a shell command. His batch file is calling my plugin which I have written to output data to a file based on the parameters that I receive via his batch file.
My problem is that when his program calls the batch file via a shell command (again, he is using VB 6), my program executes and the console writelines that I put in place in front of and after the filestream stuff all execute, but the files are not created and therefore his program does not read the file I create (CP07.txt in this case). If I manually run the batch file from Windows explorer everything works as expected. I do have a process monitor capture if that is beneficial. The program is running as the local admin on a Win7 machine (although it is not elevated), UAC is disabled, there is no anti-virus software installed, and it is not writing to a root or system folder.
I appreciate any pointers. Since the ProcMon capture is long (1400+ lines), I have not posted it.
Regards,
S
Here is a sample batchfile from the other program...
Full path to my exe
Full path to the output file
Parameter for my use
Username
Password
C:\SpecifiedDir\myprogram.exe C:\Specified\Directory\CP07.txt parameter username password
I am overwriting the output file parameter as you can see because it did not work initially the other way (I think maybe something to do with the slashes being escaped or something) and I wanted to start with a simple and working program and then clean it up from there.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace Plugin
{
class Program
{
static void Main(string[] args)
{
Console.Write("Press any key to begin: ");
Console.Write("Starting...", Console.ReadLine());
//Console.WriteLine("Done");
Console.WriteLine("Number of command line parameters = {0}",args.Length);
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
}
Console.WriteLine("");
TextWriter defaultOutputMethod = Console.Out;
TextWriter defaultErrorOutputMethod = Console.Error;
FileStream fStream;
StreamWriter strWriter;
FileStream fErrorStream;
StreamWriter strErrorWriter;
try
{
fStream = new FileStream("./Redirect.txt", FileMode.OpenOrCreate, FileAccess.Write);
strWriter = new StreamWriter(fStream);
}
catch (Exception e)
{
Console.WriteLine("Cannot open Redirect.txt for writing");
Console.WriteLine(e.Message);
return;
}
try
{
fErrorStream = new FileStream("./RedirectError.txt", FileMode.OpenOrCreate, FileAccess.Write);
strErrorWriter = new StreamWriter(fErrorStream);
}
catch (Exception e)
{
Console.WriteLine("Cannot open RedirectError.txt for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(strWriter);
Console.SetError(strErrorWriter);
Console.WriteLine("Number of command line parameters = {0}", args.Length);
for (int i = 0; i < args.Length; i++)
{
Console.WriteLine("Arg[{0}] = [{1}]", i, args[i]);
}
// Store parameters into variables for reference
string pSuccess = "OK";
string pFail = "FAIL";
string pOutputFile = args[0];
string pLookupType = args[1];
string pUserName = args[2];
string pPassword = args[3];
Console.SetOut(defaultOutputMethod);
// Console.SetError(defaultErrorOutputMethod);
strWriter.Close();
fStream.Close();
// Setup Commnet filestream and stream writer, and assign output to stream if file successfully created
FileStream fCommnetStream;
StreamWriter strCommnetWriter;
string sCommnetOutputFile = #"./CP07.txt";
try
{
fCommnetStream = new FileStream(sCommnetOutputFile, FileMode.OpenOrCreate, FileAccess.Write);
strCommnetWriter = new StreamWriter(fCommnetStream);
}
catch (Exception e)
{
Console.WriteLine("Cannot open " + sCommnetOutputFile + " for writing");
Console.WriteLine(e.Message);
return;
}
Console.SetOut(strCommnetWriter);
// Test Variables to determine output: Success or Failure
string sSuccessPass = "1111";
string sFailPass = "0000";
if (pPassword == sSuccessPass)
{
Console.WriteLine(pSuccess);
}
else if (pPassword == sFailPass)
{
Console.WriteLine(pFail);
}
else
{
Console.WriteLine("OTHER");
}
Console.WriteLine("Output File: <" + pOutputFile + ">");
Console.WriteLine("Lookup Type: <" + pLookupType + ">");
Console.WriteLine("User Name: <" + pUserName + ">");
Console.WriteLine("User Pass: <" + pPassword + ">");
Console.SetOut(defaultOutputMethod);
Console.SetError(defaultErrorOutputMethod);
strCommnetWriter.Close();
fCommnetStream.Close();
strErrorWriter.Close();
fErrorStream.Close();
Console.Write("Press any key to finish: ");
Console.Write("Ending...", Console.ReadLine());
//Console.WriteLine("Done");
}
}
}
I guess the problem is that you are writing into the "current directory", which can be anything when your program is started by a batch file, which itself has been started by another application. It is not impossible that your files are written into the directory where the batch file resides :)
Related
using System;
using System.IO;
namespace File_Dumping_Script
{
class Program
{
static void Main(string[] args)
{
Random rn = new Random();
string fileName = Convert.ToString(rn.Next(1000));
string path = ("C:\\Users\\taylo\\OneDrive\\Desktop\\FileTesting\\" + fileName);
if (File.Exists(path))
{
fileName = Convert.ToString(rn.Next(1000));
path = ("C:\\Users\\taylo\\OneDrive\\Desktop\\FileTesting\\" + fileName + ".txt");
}
File.CreateText(path);
StreamWriter sw = new StreamWriter(path);
Console.Write("Please enter a seed for the random numbers: ");
int seed = Convert.ToInt32(Console.ReadLine());
int written = 0;
while (written != seed-1)
{
written = rn.Next(seed);
sw.Write(" "+written);
Console.WriteLine(written);
}
sw.Write("\n Process ended.");
Console.WriteLine("Process complete.");
Console.ReadLine();
}
}
}
I want this program to create a file with a random number for a name, and then write a bunch of random numbers to that file. I am currently facing a problem that the File.CreateText(); is using the path, which means that the StreamWriter cannot create an object based off that path. Is there any way I can stop the File.CreateText(); from using the file so the StreamWriter can access it instead?
Also, as a secondary, less important, problem, the files created are not text files, and the way I have tried to fix that with the path = ("C:\\Users\\taylo\\OneDrive\\Desktop\\FileTesting\\" + fileName); doesn't make it a text file and nor does the File.CreateText(); How do I make it a text file instead of a 'file'?
Thank you in advance,
Taylor
I have here a piece of code for my class where I am entering values that are being written into a .txt and .bin file.
My problems are that my .txt file ends up being empty and my .bin file is not writing in binary.
I believe I have written and closed the .bin file and .txt correctly but my inputs are not being stored correctly
Here is my code
static void Main(string[] args)
{
string numberOfStudents, studentName, studentHeight, studentWeight;
int studentInput = 0, height;
bool numberOutput, heightOutput, weightOutput;
double weight;
Console.Write("Enter number of students: ");
numberOfStudents = Console.ReadLine();
numberOutput = int.TryParse(numberOfStudents, out studentInput);
if (numberOutput == true)
{
if (studentInput <= 0)
{
Console.WriteLine("Number of students must be a positive integer (greater than 0)!");
Console.ReadKey();
}
else
{
for (int i = 1; i <= studentInput; i++)
{
Console.Write("Enter student name: ");
studentName = Console.ReadLine();
Console.Write("Enter student height in centimetres: ");
studentHeight = Console.ReadLine();
heightOutput = int.TryParse(studentHeight, out height);
Console.Write("Enter student weight in kilograms: ");
studentWeight = Console.ReadLine();
weightOutput = double.TryParse(studentWeight, out weight);
try
{
StreamWriter outputFile;
outputFile = new StreamWriter("test.txt");
outputFile.Write(numberOfStudents + studentName + studentHeight + studentWeight);
outputFile.Close();
}
catch (System.IO.IOException exc)
{
Console.WriteLine("There was an error!: " + exc.Message);
}
try
{
FileStream outputFile = new FileStream("outFile.bin", FileMode.Create);
BinaryWriter BinFile = new BinaryWriter(outputFile);
BinFile.Write(studentName + " " + studentHeight + " " + studentWeight);
BinFile.Close();
}
catch (System.IO.IOException exc)
{
Console.WriteLine("There was an error!: " + exc.Message);
}
FileStream dataOutput = new FileStream("Database", FileMode.Create);
BinaryWriter databaseFile = new BinaryWriter(dataOutput);
StreamWriter textOutput = new StreamWriter("outText.txt");
databaseFile.Write(studentName + " " + studentHeight + " " + studentWeight);
databaseFile.Close();
textOutput.Close();
}
}
}
Thank you
You're almost there but there are a few issues with the code and it could be tidied up a little.
You are creating 3 files: outFile.bin, outText.txt, and test.txt. No data/text is written to outFile.txt, it is opened then closed a few lines later. Look in test.txt, it will have the last students data (see next point).
You are writing the files in a loop, which is overwriting the data, so only the last users data is being written to the file. Use outputFile = new StreamWriter("test.txt", true) this overload of StreamWriter will allow you to choose to append to the file (true) or overwrite (false).
I'd recommend looking at the using() statement when writing to file or any class that implements IDisposable. For example, when opening the StreamWriter you could do using (var outputFile = new StreamWriter("test.txt", true)) { }. This ensures the streamwriter is closed and disposed by the garbage collector, (For example, you are not closing the dataOutput file stream, if this was in a using(){} block it would automatically be handled for you)
This could be refactored into using just one try {} catch {} block, you do not need a separate try/catch for each time you write to a file.
From the Docs, the BinaryWriter class
Writes primitive types in binary to a stream and supports writing strings in a specific encoding.
So, the binary writer is writing in binary, but the data it's writing are strings. It could easily write int, double, bool, etc.
Here's the code in your try/catch blocks tidied up a bit (this only creates test.txt and outFile.bin):
try
{
// will open or create file in 'append' mode
using (var outputFile = new StreamWriter("test.txt", true))
{
outputFile.Write($"{numberOfStudents}, {studentName}, {studentHeight},{studentWeight}");
outputFile.Write(Environment.NewLine);
}
using (BinaryWriter databaseFile = new BinaryWriter(File.Open("outFile.bin", FileMode.Append)))
{
databaseFile.Write(studentName + " " + studentHeight + " " + studentWeight);
}
}
catch (System.IO.IOException exc)
{
Console.WriteLine("There was an error!: " + exc.Message);
}
I try to create a file after checking if the directory exists, and if the file exists.
But When my program gets to this line I get the error that I can't create the file because it's already being used by another process.
The weird thing is that it shouldn't.
Even when the file doesn't exist.
File.Create(Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile).Close()
the error occurs in this part of the code, catch not included.
I know that I should have used Using() but This should work too.
I don't fancy to redo this part that way untill it works this way.
if (!System.IO.Directory.Exists(System.IO.Directory.GetCurrentDirectory() + "\\Channels"))
{
connection.Logger.Log("making " + System.IO.Directory.GetCurrentDirectory() + "\\Channels", false, LogMode.Info);
System.IO.Directory.CreateDirectory(System.IO.Directory.GetCurrentDirectory() + "\\Channels");
}
string saveFile = Program.RemoveForbiddenFileCharacters(this.ChannelName + ".Channel");
string saveFilePath = System.IO.Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile;
FileStream fileStream = null;
StreamWriter streamWriter = null;
try
{
if (File.Exists(Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile))
{
File.Delete(Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile);
}
File.Create(Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile).Close();
streamWriter = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile);
//safe stuff to file
streamWriter.Close();
}
catch (Exception e)
Nothing is wrong with the code you listed here and you need to provide more information for an answer.
I.e., I created a console application that consists of the following c# code and it executes without a problem and creates the file:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string saveFile = "test.txt";
try
{
if (File.Exists(Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile))
{
File.Delete(Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile);
}
File.Create(Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile).Close();
StreamWriter streamWriter = new StreamWriter(System.IO.Directory.GetCurrentDirectory() + "\\Channels\\" + saveFile);
//safe stuff to file
streamWriter.Close();
}
catch (Exception ex)
{
}
}
}
}
Of course the file name had to be "hard coded" in, but you can see that the code is generally the same and if you copy it into a new console application you will also see that it works.
If you've just deleted the file, then the OS might prevent you from creating it within a few seconds because it's not completely done deleting it yet.
Why don't you just open the file for writing, instead of deleting and recreating it?
I have created a class library with some functionality and maintaining a log file to track the steps executed. If i run this class library in debug mode it is successfully creating log file.
But, I have created the cab file after creating the tlb file of that class library and installed into the system. Now i am using that library, all the functions are working properly, only logs files are not written.
I've used the code to create log file is below-
public static void LogTrace(string LogMessage)
{
try
{
string LogError = string.Empty;
String DirPath = string.Empty;
DirPath= Convert.ToString(ConfigurationSettings.AppSettings["DirPath"]);
LogError = Convert.ToString(ConfigurationSettings.AppSettings["LogError"]);
//if logging is not required
if (LogError.ToLower() == "true")
{
if (DirPath == null || DirPath == string.Empty)
DirPath = #"C:\LogAndError";
if (LogError == null || LogError == string.Empty)
LogError = "True";
//creation of date wise file name
string LogFileName = DirPath + "\\Log_ " + DateTime.Now.ToString("MM_dd_yyyy") + ".txt";
createLogAndErrorFile(DirPath);
StreamWriter streamWriter = null;
streamWriter = new StreamWriter(LogFileName, true);
streamWriter.WriteLine("Time :" + DateTime.Now.ToString() + " ");
streamWriter.WriteLine(LogMessage);
streamWriter.WriteLine(Environment.NewLine);
streamWriter.Flush();
streamWriter.Close();
}
}
catch
{
//We are not throwing any exception because all the exeption is logged using this method
//and throwing the exception could lead to recursive call of function.
}
}
public static void createLogAndErrorFile(string DirPath)
{
if (!Directory.Exists(DirPath))
Directory.CreateDirectory(DirPath);
}
}
Am i missing something ?
Verify that you have permission to acces to your file
Place your code in try catch block and capture exception
I suggest you to use using block
try
{
var path = Path.Combine(DirPath, string.Concat("\\Log_",DateTime.Now.ToString("MM_dd_yyyy"), ".txt"));
using (StreamWriter streamWriter = new StreamWriter(path))
{
streamWriter.WriteLine("Time :" + DateTime.Now.ToString() + " ");
streamWriter.WriteLine(LogMessage);
streamWriter.WriteLine(Environment.NewLine);
}
}
catch(Exception ex)
{
Console.Write(ex.Message);
throw ex;
}
I'm trying to extract an ISO to a folder with the same name without .iso on the end.
I'm having a problem with winrar as it will not start the extract when I start up with the seach starting in the folder with the ISO.
UPDATED with answer code
private void ExtractISO(string toExtract, string folderName)
{
// reads the ISO
CDReader Reader = new CDReader(File.Open(toExtract, FileMode.Open), true);
// passes the root directory the folder name and the folder to extract
ExtractDirectory(Reader.Root, folderName /*+ Path.GetFileNameWithoutExtension(toExtract)*/ + "\\", "");
// clears reader and frees memory
Reader.Dispose();
}
private void ExtractDirectory(DiscDirectoryInfo Dinfo, string RootPath, string PathinISO)
{
if (!string.IsNullOrWhiteSpace(PathinISO))
{
PathinISO += "\\" + Dinfo.Name;
}
RootPath += "\\" + Dinfo.Name;
AppendDirectory(RootPath);
foreach (DiscDirectoryInfo dinfo in Dinfo.GetDirectories())
{
ExtractDirectory(dinfo, RootPath, PathinISO);
}
foreach (DiscFileInfo finfo in Dinfo.GetFiles())
{
using (Stream FileStr = finfo.OpenRead())
{
using (FileStream Fs = File.Create(RootPath + "\\" + finfo.Name)) // Here you can Set the BufferSize Also e.g. File.Create(RootPath + "\\" + finfo.Name, 4 * 1024)
{
FileStr.CopyTo(Fs, 4 * 1024); // Buffer Size is 4 * 1024 but you can modify it in your code as per your need
}
}
}
}
static void AppendDirectory(string path)
{
try
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
catch (DirectoryNotFoundException Ex)
{
AppendDirectory(Path.GetDirectoryName(path));
}
catch (PathTooLongException Ex)
{
AppendDirectory(Path.GetDirectoryName(path));
}
}
The user selects the folder to extract (.ISO) toExtract. I then use it in the Process.Start() in the background worker. That just seems to open the mounting software and doesn't extract the ISO to the desired folder name.
Thanks in advance for your help.
Or if anyone could give me a batch to extract the ISO instead and to call it from c# passing toExtract and the folder name that would be helpful too.
Thanks
If external Class Libraries are OK!
Then use SevenZipSharp or .NET DiscUtils to extract ISO's...
These two ClassLibraries can manage ISO and Extract them!
For DiscUtils you can find some codes for ISO Management [CDReader Class] at the Link I provided.
But For SevenZipSharp, Please Explore the ClassLibrary source and find the Code to Extract or Google to find it!
To get the Name of the folder just use Path.GetFileNameWithoutExtension((string)ISOFileName) which will return "ISOFile" for an iso named "ISOFile.iso". And then you can use it with your desired path.
UPDATE
Code To Extract ISO Image with DiscUtils :
using DiscUtils;
using DiscUtils.Iso9660;
void ExtractISO(string ISOName, string ExtractionPath)
{
using (FileStream ISOStream = File.Open(ISOName, FileMode.Open))
{
CDReader Reader = new CDReader(ISOStream, true, true);
ExtractDirectory(Reader.Root, ExtractionPath + Path.GetFileNameWithoutExtension(ISOName) + "\\", "");
Reader.Dispose();
}
}
void ExtractDirectory(DiscDirectoryInfo Dinfo, string RootPath, string PathinISO)
{
if (!string.IsNullOrWhiteSpace(PathinISO))
{
PathinISO += "\\" + Dinfo.Name;
}
RootPath += "\\" + Dinfo.Name;
AppendDirectory(RootPath);
foreach (DiscDirectoryInfo dinfo in Dinfo.GetDirectories())
{
ExtractDirectory(dinfo, RootPath, PathinISO);
}
foreach (DiscFileInfo finfo in Dinfo.GetFiles())
{
using (Stream FileStr = finfo.OpenRead())
{
using (FileStream Fs = File.Create(RootPath + "\\" + finfo.Name)) // Here you can Set the BufferSize Also e.g. File.Create(RootPath + "\\" + finfo.Name, 4 * 1024)
{
FileStr.CopyTo(Fs, 4 * 1024); // Buffer Size is 4 * 1024 but you can modify it in your code as per your need
}
}
}
}
static void AppendDirectory(string path)
{
try
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}
catch (DirectoryNotFoundException Ex)
{
AppendDirectory(Path.GetDirectoryName(path));
}
catch (PathTooLongException Exx)
{
AppendDirectory(Path.GetDirectoryName(path));
}
}
Use It with Like This :
ExtractISO(ISOFileName, Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "\\");
Working! Tested By Me!
And Of Course You can always add more Optimization to the code...
This Code is Just a Basic One!
For UDF or for making Windows ISO Files after servicing(DISM) with out needs the above accepted answer is not working for me so i tried this working method with DiscUtils
using DiscUtils;
public static void ReadIsoFile(string sIsoFile, string sDestinationRootPath)
{
Stream streamIsoFile = null;
try
{
streamIsoFile = new FileStream(sIsoFile, FileMode.Open);
DiscUtils.FileSystemInfo[] fsia = FileSystemManager.DetectDefaultFileSystems(streamIsoFile);
if (fsia.Length < 1)
{
MessageBox.Show("No valid disc file system detected.");
}
else
{
DiscFileSystem dfs = fsia[0].Open(streamIsoFile);
ReadIsoFolder(dfs, #"", sDestinationRootPath);
return;
}
}
finally
{
if (streamIsoFile != null)
{
streamIsoFile.Close();
}
}
}
public static void ReadIsoFolder(DiscFileSystem cdReader, string sIsoPath, string sDestinationRootPath)
{
try
{
string[] saFiles = cdReader.GetFiles(sIsoPath);
foreach (string sFile in saFiles)
{
DiscFileInfo dfiIso = cdReader.GetFileInfo(sFile);
string sDestinationPath = Path.Combine(sDestinationRootPath, dfiIso.DirectoryName.Substring(0, dfiIso.DirectoryName.Length - 1));
if (!Directory.Exists(sDestinationPath))
{
Directory.CreateDirectory(sDestinationPath);
}
string sDestinationFile = Path.Combine(sDestinationPath, dfiIso.Name);
SparseStream streamIsoFile = cdReader.OpenFile(sFile, FileMode.Open);
FileStream fsDest = new FileStream(sDestinationFile, FileMode.Create);
byte[] baData = new byte[0x4000];
while (true)
{
int nReadCount = streamIsoFile.Read(baData, 0, baData.Length);
if (nReadCount < 1)
{
break;
}
else
{
fsDest.Write(baData, 0, nReadCount);
}
}
streamIsoFile.Close();
fsDest.Close();
}
string[] saDirectories = cdReader.GetDirectories(sIsoPath);
foreach (string sDirectory in saDirectories)
{
ReadIsoFolder(cdReader, sDirectory, sDestinationRootPath);
}
return;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
it has extracted from a application source ISOReader but modified for my requirements
total source is available at http://www.java2s.com/Open-Source/CSharp_Free_CodeDownload/i/isoreader.zip
Try this:
string Desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
Process.Start("Winrar.exe", string.Format("x {0} {1}",
Desktop + "\\test.rar",
Desktop + "\\SomeFolder"));
That would extract the file test.rar to the folder SomeFolder. You can change the .rar extention to .iso, it'll work the same.
As far as I can see in your current code, there is no command given to extract a file, and no path to the file that has to be extracted. Try this example and let me know if it works =]
P.S. If you'd like to hide the extracting screen, you can set the YourProcessInfo.WindowStyle to ProcessWindowStyle.Hidden.
I hace confrunted recently with this kind of .iso extraction issue. After trying several methods, 7zip did the job for me, you just have to make sure that the latest version of 7zip is installed on your system. Maybe it will help
try
{
Process cmd = new Process();
cmd.StartInfo.FileName = "cmd.exe";
cmd.StartInfo.RedirectStandardInput = true;
cmd.StartInfo.RedirectStandardOutput = true;
cmd.StartInfo.CreateNoWindow = false;
cmd.StartInfo.UseShellExecute = false;
cmd.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
cmd.Start();
cmd.StandardInput.WriteLine("C:");
//Console.WriteLine(cmd.StandardOutput.Read());
cmd.StandardInput.Flush();
cmd.StandardInput.WriteLine("cd C:\\\"Program Files\"\\7-Zip\\");
//Console.WriteLine(cmd.StandardOutput.ReadToEnd());
cmd.StandardInput.Flush();
cmd.StandardInput.WriteLine(string.Format("7z x -y -o{0} {1}", source, copyISOLocation.TempIsoPath));
//Console.WriteLine(cmd.StandardOutput.ReadToEnd());
cmd.StandardInput.Flush();
cmd.StandardInput.Close();
cmd.WaitForExit();
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}
catch (Exception e)
{
Console.WriteLine(e.Message + "\n" + e.StackTrace);
if (e.InnerException != null)
{
Console.WriteLine(e.InnerException.Message + "\n" + e.InnerException.StackTrace);
}
}