I want to loop through all images in a folder, retrieve each image's name and pass an argument using the name. This is what I have:
foreach (string imageFile in Directory.EnumerateFiles(filePath))
{
//Get image name and save it as string
string args = "something"; //a line of argument with image name in it
Process.Start("cmd", #"/c cd C:\Tesseract-OCR && " + args);
}
The problem with above code is that, for each image file, it will open up a new command prompt. Instead, I want something like:
Process.Start("cmd", #"/k cd C:\Tesseract-OCR");
foreach (string imageFile in Directory.EnumerateFiles(filePath))
{
//For each imageFile I have, pass an argument to the opened cmd prompt
}
There are a few methods, but generally the simplest is to create a batch file with all of the commands you want to execute then pass that as a parameter to cmd.
Something like this:
string imageFolder = #"C:\Path\To\Images";
string batchFile = #"C:\Temp\cmds.cmd";
string outputFile = #"C:\Temp\cmds.log";
// substitute your own command here. "{0}" will be substituted for filename
string command = #"attrib ""{0}"" >> """ + outputFile + #"""";
// delete the batch file if it exists
if (File.Exists(batchFile))
File.Delete(batchFile);
// create batch file from content of image folder
using (var writer = File.CreateText(batchFile))
{
writer.WriteLine("#echo off");
foreach (var file in Directory.EnumerateFiles(imageFolder, "*.jpg"))
writer.WriteLine(command, file);
}
// Delete the output file if it exists
if (File.Exists(outputFile))
File.Delete(outputFile);
// Execute the batch
var p = Process.Start("cmd", #"/c """ + batchFile + #"""");
p.WaitForExit();
After that completes you can grab the content of the output file and parse it for results. If you need a break between the outputs, just echo something distinctive between each one. Maybe something like:
// create batch file from content of image folder
using (var writer = File.CreateText(batchFile))
{
writer.WriteLine("#echo off");
foreach (var file in Directory.EnumerateFiles(imageFolder, "*.jpg"))
{
writer.WriteLine(#"echo -----Start: {0}>>""{1}""", file, outputFile);
writer.WriteLine(command, file);
writer.WriteLine(#"echo -----End: {0}>>""{1}""", file, outputFile);
}
}
That way you get the filename in the output as well to help with parsing.
Another option is to use full stream redirection to streams that you can write commands to and read responses from. This would allow you to have a command prompt running somewhere in the background that you can issue commands to. Seems simple, but honestly it takes a lot of work to get just right. If you want to go this way I'd suggest redirecting all three standard streams.
Why not have the program create a batch file containing all the files/commands to be executed, then use Process.Start to execute the batch file?
You can use Directory.GetFiles() to get a string array of all the files in a directory. Then use String.Join() to merge the array into one long string of file names separated by space. I would also wrap each item in quotes if your path or files contain spaces.
const string QUOTE = "\"";
const string SPACE = " ";
const string SEPARATOR = QUOTE + SPACE + QUOTE;
string[] files = Directory.GetFiles(filePath, "*.png");
string allFiles = QUOTE + String.Join(SEPARATOR, files) + QUOTE;
Console.WriteLine(#"cmd.exe /c cd C:\Tesseract-OCR && " + allFiles);
I am trying to implement a functionality using Magick.NET in C#.
Previously I was using:-
// Convert to a png.
Process p = new Process();
p.StartInfo.FileName = #"C:\Program Files\ImageMagick-6.2.8-Q16\convert.exe";
p.StartInfo.Arguments = "-scale 60% \"" + svg + "\" \"" + png + "\"";
p.StartInfo.CreateNoWindow = true;
p.Start();
p.WaitForExit();
TransmitFile(context, png);
I want to move away from having to store convert.exe on the server.....Now I want to use something that will be in code and doesn't need to reference an executable file on the server:-
// Pseudo-code:-
MagickImage img = new MagicImage();
Image.Add(svg);
Image.Format = MagickFormat.png;
Image.Scale = 60%;
But I cannot find enough documentation to implement the same functionality that I was using before. Is there a place with appropriate documentations? I have googled quite a bit, without success.
There are some examples of how to use Magick.NET available here.
An example of how to convert one image to another image can be found here. But there is no example for -scale 60%.
Most options from the command line have the same name in the MagickImage class. Your command convert input.svg -scale 60% output.png translates to this:
using (MagickImage image = new MagickImage("input.svg"))
{
image.Scale(new Percentage(60));
image.Write("output.png");
}
I am running c# application in service mode. And i am using pdf2swf tool to convert odf to swf format. Images saved in pdf is converting. But if any test adding to pdf is not getting converted in service mode.
But when run as UI mode(Consoleapplication.exe) then everything is getting converted.
string inputFileName = this.Filename;
string outputFileName = inputFileName.Replace("pdf", "swf");
StringBuilder sb = new StringBuilder();
sb.AppendFormat("{0} -o {1}", inputFileName, outputFileName);
string executingDirPath = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", "");
string dataDirectoryPath = Path.Combine(executingDirPath, "pdf2swf.exe");
ProcessStartInfo psi = new ProcessStartInfo(dataDirectoryPath, sb.ToString());
psi.UseShellExecute = false;
System.Diagnostics.Process pdf2swf = new System.Diagnostics.Process();
pdf2swf.StartInfo = psi;
pdf2swf.Start();
pdf2swf.WaitForExit();
pdf2swf.Close();
pdf2swf.Dispose();
Regards
Sangeetha
Direct using process to start pdf2swf.ext maybe had some privilege problems.I used another way to solve this problem,write a batch file,then running the batch file by process.
Batch file sample:
c:
cd C:\Program Files (x86)\SWFTools\
pdf2swf.exe -f -T 9 -t "%1" -o "%2"
Code in program:
Process p = new Process();
string path = basePath + "/plugin/ConvertToSwf.bat";//batch file path
ProcessStartInfo pi = new ProcessStartInfo(path, filePath + " " + swfPath);//passing the file path and converted file path to batch file
pi.UseShellExecute = false;
pi.RedirectStandardOutput = true;
p.StartInfo = pi;
p.Start();
p.WaitForExit();
I faced a similar problem recently. I solved the issue by adding a separate console application(Consoleapplication.exe) with administrative-rights that runs on my server without shell.
Also, try to upgrade to the newest version of pdf2swf.
FYI. I recently had this problem (thought it was fonts not being embedded but actually was missing all text in converted swf). What fixed it for me was to set:
pi.UseShellExecute = false;
AND set the working directory;
pi.WorkingDirectory = "C:\windows\temp"; // path where read & write is
I'm developing a console application that parse xml files and generate a txt file. I have created the file path to store the new file, but this is having white spaces, like this:
string filePath = "C:\\Program Files\\my path\\fileName.txt"
but I'm creating the path using:
string filePath = Path.Combine(temp, "fileName.txt");
while temp is the previous path. And when I call:
StreamWriter sw = File.CreateText(filePath);
Is giving this exception:
Could not find a part of the path: filePath
Can someone help me with this issue?? how can I create the file with this path?
there looks like a problem with you file path
try#"C:\Program Files\my path\fileName.txt"
Note: You've updated your question with the changes mentioned in the comments.
Your issue is probably that 'my path' doesn't exist as this console application works OK for me when run as an administrator. When not run I get an UnathorizedAccessException
class Program
{
static void Main(string[] args)
{
try
{
var temp = #"C:\\Program Files\\my path\\";
string filePath = Path.Combine(temp, "fileName.txt");
StreamWriter sw = File.CreateText(filePath);
Console.WriteLine("I got here");
}
catch (Exception)
{
Console.WriteLine("I didn't");
//
}
}
}
Use this:
string filePath = #"C:\Program Files\my path\fileName.txt"
You have single backslashes in the string. Make them double backslashes:
string filePath = "C:\\Program Files\\my path\\fileName.txt"
How can I create 7-Zip archives from my C# console application? I need to be able to extract the archives using the regular, widely available 7-Zip program.
Here are my results with the examples provided as answers to this question
"Shelling out" to 7z.exe - this is the simplest and most effective approach, and I can confirm that it works nicely. As workmad3 mentions, I just need to guarantee that 7z.exe is installed on all target machines, which is something I can guarantee.
7Zip in memory compression - this refers to compressing cookies "in-memory" before sending to the client; this method seems somewhat promising. The wrapper methods (wrapping the LZMA SDK) return type byte[]. When I write the byte[] array to a file, I can't extract it using 7-Zip (File.7z is not supported archive).
7zSharp Wrapper (found on CodePlex) - this wraps the 7z exe/LZMA SDK. I referenced the project from my app, and it successfully created some archive files, but I was unable to extract the files using the regular 7-Zip program (File.7z is not supported archive).
7Zip SDK aka LZMA SDK - I guess I'm not smart enough to figure out how to use this (which is why I posted here)... Any working code examples that demonstrate creating a 7zip archive that is able to be extracted by the regular 7zip program?
CodeProject C# (.NET) Interface for 7-Zip Archive DLLs - only supports extracting from 7zip archives... I need to create them!
SharpZipLib - According to their FAQ, SharpZipLib doesn't support 7zip.
EggCafe 7Zip cookie example This is an example (zipping cookie) with the DLL of 7Zip.
CodePlex Wrapper
This is an open source project that warp zipping function of 7z.
7Zip SDK The official SDK for 7zip (C, C++, C#, Java) <---My suggestion
.Net zip library by SharpDevelop.net
CodeProject example with 7zip
SharpZipLib Many zipping
If you can guarantee the 7-zip app will be installed (and in the path) on all target machines, you can offload by calling the command line app 7z. Not the most elegant solution but it is the least work.
SevenZipSharp is another solution. Creates 7-zip archives...
Here's a complete working example using the SevenZip SDK in C#.
It will write, and read, standard 7zip files as created by the Windows 7zip application.
PS. The previous example was never going to decompress because it never wrote the required property information to the start of the file.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SevenZip.Compression.LZMA;
using System.IO;
using SevenZip;
namespace VHD_Director
{
class My7Zip
{
public static void CompressFileLZMA(string inFile, string outFile)
{
Int32 dictionary = 1 << 23;
Int32 posStateBits = 2;
Int32 litContextBits = 3; // for normal files
// UInt32 litContextBits = 0; // for 32-bit data
Int32 litPosBits = 0;
// UInt32 litPosBits = 2; // for 32-bit data
Int32 algorithm = 2;
Int32 numFastBytes = 128;
string mf = "bt4";
bool eos = true;
bool stdInMode = false;
CoderPropID[] propIDs = {
CoderPropID.DictionarySize,
CoderPropID.PosStateBits,
CoderPropID.LitContextBits,
CoderPropID.LitPosBits,
CoderPropID.Algorithm,
CoderPropID.NumFastBytes,
CoderPropID.MatchFinder,
CoderPropID.EndMarker
};
object[] properties = {
(Int32)(dictionary),
(Int32)(posStateBits),
(Int32)(litContextBits),
(Int32)(litPosBits),
(Int32)(algorithm),
(Int32)(numFastBytes),
mf,
eos
};
using (FileStream inStream = new FileStream(inFile, FileMode.Open))
{
using (FileStream outStream = new FileStream(outFile, FileMode.Create))
{
SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder();
encoder.SetCoderProperties(propIDs, properties);
encoder.WriteCoderProperties(outStream);
Int64 fileSize;
if (eos || stdInMode)
fileSize = -1;
else
fileSize = inStream.Length;
for (int i = 0; i < 8; i++)
outStream.WriteByte((Byte)(fileSize >> (8 * i)));
encoder.Code(inStream, outStream, -1, -1, null);
}
}
}
public static void DecompressFileLZMA(string inFile, string outFile)
{
using (FileStream input = new FileStream(inFile, FileMode.Open))
{
using (FileStream output = new FileStream(outFile, FileMode.Create))
{
SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder();
byte[] properties = new byte[5];
if (input.Read(properties, 0, 5) != 5)
throw (new Exception("input .lzma is too short"));
decoder.SetDecoderProperties(properties);
long outSize = 0;
for (int i = 0; i < 8; i++)
{
int v = input.ReadByte();
if (v < 0)
throw (new Exception("Can't Read 1"));
outSize |= ((long)(byte)v) << (8 * i);
}
long compressedSize = input.Length - input.Position;
decoder.Code(input, output, compressedSize, outSize, null);
}
}
}
public static void Test()
{
CompressFileLZMA("DiscUtils.pdb", "DiscUtils.pdb.7z");
DecompressFileLZMA("DiscUtils.pdb.7z", "DiscUtils.pdb2");
}
}
}
I used the sdk.
eg:
using SevenZip.Compression.LZMA;
private static void CompressFileLZMA(string inFile, string outFile)
{
SevenZip.Compression.LZMA.Encoder coder = new SevenZip.Compression.LZMA.Encoder();
using (FileStream input = new FileStream(inFile, FileMode.Open))
{
using (FileStream output = new FileStream(outFile, FileMode.Create))
{
coder.Code(input, output, -1, -1, null);
output.Flush();
}
}
}
string zipfile = #"E:\Folderx\NPPES.zip";
string folder = #"E:\TargetFolderx";
ExtractFile(zipfile,folder);
public void ExtractFile(string source, string destination)
{
// If the directory doesn't exist, create it.
if (!Directory.Exists(destination))
Directory.CreateDirectory(destination);
//string zPath = ConfigurationManager.AppSettings["FileExtactorEXE"];
// string zPath = Properties.Settings.Default.FileExtactorEXE; ;
string zPath=#"C:\Program Files\7-Zip\7zG.exe";
try
{
ProcessStartInfo pro = new ProcessStartInfo();
pro.WindowStyle = ProcessWindowStyle.Hidden;
pro.FileName = zPath;
pro.Arguments = "x \"" + source + "\" -o" + destination;
Process x = Process.Start(pro);
x.WaitForExit();
}
catch (System.Exception Ex) { }
}
Just Install 7 zip from source and pass the parameter to the method.
Thanks. Please like the answer.
I use this code
string PZipPath = #"C:\Program Files\7-Zip\7z.exe";
string sourceCompressDir = #"C:\Test";
string targetCompressName = #"C:\Test\abc.zip";
string CompressName = targetCompressName.Split('\\').Last();
string[] fileCompressList = Directory.GetFiles(sourceCompressDir, "*.*");
if (fileCompressList.Length == 0)
{
MessageBox.Show("No file in directory", "Important Message");
return;
}
string filetozip = null;
foreach (string filename in fileCompressList)
{
filetozip = filetozip + "\"" + filename + " ";
}
ProcessStartInfo pCompress = new ProcessStartInfo();
pCompress.FileName = PZipPath;
if (chkRequestPWD.Checked == true)
{
pCompress.Arguments = "a -tzip \"" + targetCompressName + "\" " + filetozip + " -mx=9" + " -p" + tbPassword.Text;
}
else
{
pCompress.Arguments = "a -tzip \"" + targetCompressName + "\" \"" + filetozip + "\" -mx=9";
}
pCompress.WindowStyle = ProcessWindowStyle.Hidden;
Process x = Process.Start(pCompress);
x.WaitForExit();
Some additional test-info on #Orwellophile code using a 17.9MB textfile.
Using the property values in the code-example "as is" will have a HUGE negative impact on performance, it takes 14.16 sec.
Setting the properties to the following do the same job at 3.91 sec (i.a. the archive will have the same container info which is: you can extract and test the archive with 7zip but there are no filename information)
Native 7zip 2 sec.
CoderPropID[] propIDs = {
//CoderPropID.DictionarySize,
//CoderPropID.PosStateBits,
//CoderPropID.LitContextBits,
//CoderPropID.LitPosBits,
//CoderPropID.Algorithm,
//CoderPropID.NumFastBytes,
//CoderPropID.MatchFinder,
CoderPropID.EndMarker
};
object[] properties = {
//(Int32)(dictionary),
//(Int32)(posStateBits),
//(Int32)(litContextBits),
//(Int32)(litPosBits),
//(Int32)(algorithm),
//(Int32)(numFastBytes),
//mf,
eos
};
I did another test using native 7zip and a 1,2GB SQL backup file (.bak)
7zip (maximum compression): 1 minute
LZMA SDK (#Orwellophile with above property-setting): 12:26 min :-(
Outputfile roughly same size.
So I guess I'll myself will use a solution based on the c/c++ engine, i.a. either call the 7zip executable from c# or use squid-box/SevenZipSharp, which is a wrapper around the 7zip c/c++ dll file, and seems to be the newest fork of SevenZipSharp.
Haven't tested the wrapper, but I hope is perform just as the native 7zip. But hopefully it will give the possibility to compress stream also which you obvious cannot if you call the exe directly. Otherwise I guess there isn't mush advantage over calling the exe. The wrapper have some additional dependencies so it will not make your published project "cleaner".
By the way it seems the .Net Core team consider implementing LZMA in the system.io class in .Core ver. 5, that would be great!
(I know this is kind of a comment and not an answer but to be able to provide the code snippet it couldn't be a comment)
SharpCompress is in my opinion one of the smartest compression libraries out there. It supports LZMA (7-zip), is easy to use and under active development.
As it has LZMA streaming support already, at the time of writing it unfortunately only supports 7-zip archive reading. BUT archive writing is on their todo list (see readme). For future readers: Check to get the current status here: https://github.com/adamhathcock/sharpcompress/blob/master/FORMATS.md
Install the NuGet package called SevenZipSharp.Interop
Then:
SevenZipBase.SetLibraryPath(#".\x86\7z.dll");
var compressor = new SevenZip.SevenZipCompressor();
var filesToCompress = Directory.GetFiles(#"D:\data\");
compressor.CompressFiles(#"C:\archive\abc.7z", filesToCompress);
These easiest way is to work with .zip files instead of .7z and use Dot Net Zip
When spinning off 7zip commands to shell there are other issues like user privileges, I had issue with SevenZipSharp.
Private Function CompressFile(filename As String) As Boolean
Using zip As New ZipFile()
zip.AddFile(filename & ".txt", "")
zip.Save(filename & ".zip")
End Using
Return File.Exists(filename & ".zip")
End Function
Here is code to create and extract 7zip (based on LZMA SDK - C#)
Note: 7z archives created with same code can be unarchived. As code uses managed LZMA using earlier version of LZMA SDK