I want to access the path for my directory, but I can not. I put a breakpoint in my code:
string directoryPath = args[0];
And when i clicked on the args[0];, it showed me this image:
- args {string[3]} string[]
[0] "C:\\Users\\soft\\Documents\\Visual" string
[1] "Studio" string
[2] "2010\\Projects\\erereerer\\erereerer\\bin\\Debug\\MAXee\\" string
directoryPath null string
filesList null string[]
filesListTmp null string[]
opList null erereerer.IFileOperation[]
I have been trying to access my directory but I have been failing. I tried so many times but when I run my code its saying directory does not exist while the directory is in fact there..
This is my code:
class Program
{
static void Main(string[] args)
{
string directoryPath = args[0];
string[] filesList, filesListTmp;
IFileOperation[] opList = { new FileProcNameAfter10(),
new FileProcEnc(),
new FileProcByExt("jpeg"),
new FileProcByExt("jpg"),
new FileProcByExt("doc"),
new FileProcByExt("pdf"),
new FileProcByExt("djvu")
};
if (Directory.Exists(directoryPath))
{
filesList = Directory.GetFiles(directoryPath);
while (true)
{
Thread.Sleep(500);
filesListTmp = Directory.GetFiles(directoryPath);
foreach (var elem in Enumerable.Except<string>(filesListTmp, filesList))
{
Console.WriteLine(elem);
foreach (var op in opList)
{
if (op.Accept(elem)) op.Process(elem);
}
}
filesList = filesListTmp;
if (Console.KeyAvailable == true && Console.ReadKey(true).Key == ConsoleKey.Escape) break;
}
}
else
{
Console.WriteLine("There is no such directory.");
Console.ReadKey();
}
}
}
[0] "C:\Users\soft\Documents\Visual" string
[1] "Studio" string
[2] "2010\Projects\erereerer\erereerer\bin\Debug\MAXee\" string
It tells me that you are passing the arguments without quotes.
Call you program this way:
MyApp.exe "C:\Users\soft\Documents\Visual Studio 2010\Projects\erereerer\erereerer\bin\Debug\MAXee\"
Or just do what Blachshma said:
directoryPath = String.Join(" ", args);
Either pass the directory in quotes:
MyProgram.exe "C:\Users\soft\Documents\Visual Studio 2010\Projects\erereerer\erereerer\bin\Debug\MAXee\"
or Join the args in code:
directoryPath = String.Join(" ", args);
Related
I'm doing a project that uses python as background script and C# as guy.
My problem is that I can't figure out how to cause my GUI to automatically search for the pythonw.exe file in order to run my python scripts.
Currently I'm using this path:
ProcessStartInfo pythonInfo = new ProcessStartInfo(#"C:\\Users\\Omri\\AppData\\Local\\Programs\\Python\\Python35-32\\pythonw.exe");
but I want it to auto detect the path of pythonw.exe (I need to submit the project and it won't run on others computers unless they change the code itself)
Any suggestions may be helpful.
Inspired by #Shashi Bhushan's answer I made this function for getting the Python path reliably;
private static string GetPythonPath(string requiredVersion = "", string maxVersion = "") {
string[] possiblePythonLocations = new string[3] {
#"HKLM\SOFTWARE\Python\PythonCore\",
#"HKCU\SOFTWARE\Python\PythonCore\",
#"HKLM\SOFTWARE\Wow6432Node\Python\PythonCore\"
};
//Version number, install path
Dictionary<string, string> pythonLocations = new Dictionary<string, string>();
foreach (string possibleLocation in possiblePythonLocations) {
string regKey = possibleLocation.Substring(0, 4), actualPath = possibleLocation.Substring(5);
RegistryKey theKey = (regKey == "HKLM" ? Registry.LocalMachine : Registry.CurrentUser);
RegistryKey theValue = theKey.OpenSubKey(actualPath);
foreach (var v in theValue.GetSubKeyNames()) {
RegistryKey productKey = theValue.OpenSubKey(v);
if (productKey != null) {
try {
string pythonExePath = productKey.OpenSubKey("InstallPath").GetValue("ExecutablePath").ToString();
// Comment this in to get (Default) value instead
// string pythonExePath = productKey.OpenSubKey("InstallPath").GetValue("").ToString();
if (pythonExePath != null && pythonExePath != "") {
//Console.WriteLine("Got python version; " + v + " at path; " + pythonExePath);
pythonLocations.Add(v.ToString(), pythonExePath);
}
} catch {
//Install path doesn't exist
}
}
}
}
if (pythonLocations.Count > 0) {
System.Version desiredVersion = new System.Version(requiredVersion == "" ? "0.0.1" : requiredVersion),
maxPVersion = new System.Version(maxVersion == "" ? "999.999.999" : maxVersion);
string highestVersion = "", highestVersionPath = "";
foreach (KeyValuePair<string, string> pVersion in pythonLocations) {
//TODO; if on 64-bit machine, prefer the 64 bit version over 32 and vice versa
int index = pVersion.Key.IndexOf("-"); //For x-32 and x-64 in version numbers
string formattedVersion = index > 0 ? pVersion.Key.Substring(0, index) : pVersion.Key;
System.Version thisVersion = new System.Version(formattedVersion);
int comparison = desiredVersion.CompareTo(thisVersion),
maxComparison = maxPVersion.CompareTo(thisVersion);
if (comparison <= 0) {
//Version is greater or equal
if (maxComparison >= 0) {
desiredVersion = thisVersion;
highestVersion = pVersion.Key;
highestVersionPath = pVersion.Value;
} else {
//Console.WriteLine("Version is too high; " + maxComparison.ToString());
}
} else {
//Console.WriteLine("Version (" + pVersion.Key + ") is not within the spectrum.");
}
}
//Console.WriteLine(highestVersion);
//Console.WriteLine(highestVersionPath);
return highestVersionPath;
}
return "";
}
You can find python installation path by lookup following keys on windows machine.
HKLM\SOFTWARE\Python\PythonCore\versionnumber\InstallPath
HKCU\SOFTWARE\Python\PythonCore\versionnumber\InstallPath
for win64 bit machine
HKLM\SOFTWARE\Wow6432Node\Python\PythonCore\versionnumber\InstallPath
You can refer this post for how to read registry using C#
How to read value of a registry key c#
Find the environment variable name in Windows, for that assembly and use Environment.GetEnvironmentVariable(variableName)
Check out How to add to the pythonpath in windows 7?
An example on how to search for Python within the PATH environment variable:
var entries = Environment.GetEnvironmentVariable("path").Split(';');
string python_location = null;
foreach (string entry in entries)
{
if (entry.ToLower().Contains("python"))
{
var breadcrumbs = entry.Split('\\');
foreach (string breadcrumb in breadcrumbs)
{
if (breadcrumb.ToLower().Contains("python"))
{
python_location += breadcrumb + '\\';
break;
}
python_location += breadcrumb + '\\';
}
break;
}
}
Just change the FileName to "python.exe" if you already set python env path
private void runPython(string cmd, string args)
{
ProcessStartInfo start = new ProcessStartInfo();
start.FileName = "python.exe";
start.Arguments = string.Format("{0} {1}", cmd, args);
start.UseShellExecute = false;
start.RedirectStandardOutput = true;
using (Process process = Process.Start(start))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
Console.Write(result);
}
}
}
On my machine, with Python 3.11 installed, I can query it by defining this property:
public string PythonInstallPath
{
get => (string)Microsoft.Win32.Registry.GetValue(
#"HKEY_CURRENT_USER\SOFTWARE\Python\PythonCore\3.11\InstallPath",
"ExecutablePath", null);
}
Pythonw.exe is located in the same path, so you can do:
public string PythonWInstallPath
{
get => System.IO.Path.Combine(System.IO.Path.GetDirectoryName(PythonInstallPath),
"pythonw.exe");
}
There is also a way to look it up in the environment, check this out as an alternative.
I use a tool's binaries in a C# project called GraphViz.
The problem is I must include the binaries path as hard-coded and I don't want to do that.
IRenderer renderer = new Renderer("C:\\Program Files (x86)\\Graphviz2.38\\bin"); // todo: remove hardcoded GraphViz path
I want to mimic the linux which command.
Simply passing the binary name (e.g dot) and get the path.
GetBinaryPath("dot"); // return the above path
I'd appreciate any ideas or topics to start searching.
Note
Target OS: Windows
.NET version : 4
If you need to find path given only executable name (and installation directory is in your PATH environment variable)
Option 1:
Using where command with Process class. (test for exit code, parse the output)
Option 2:
You can get environment PATH environment variable, split it by ';' and test for your executable name existence.
First you need to find all directories where windows search for a exectuable file and that is from the environment variable %PATH%.
Then you need to find all extensions (.com, .exe, .bat etc) from %PATHEXT%.
Then you just check them like this:
internal class Program {
private static void Main(string[] args) {
if (args.Length != 1) {
Console.WriteLine("Incorrect usage!");
return;
}
var extensions = GetExecutableExtensions(args[0]);
var paths = GetPaths();
var exeFile = GetFirstExecutableFile(args[0], extensions, paths);
if (exeFile == null) {
Console.WriteLine("No file found!");
}
else {
Console.WriteLine(exeFile);
}
}
private static string GetFirstExecutableFile(string file, string[] extensions, string[] paths) {
foreach (var path in paths) {
var filename = Path.Combine(path, file);
if (extensions.Length == 0) {
if (File.Exists(filename)) {
return filename;
}
}
else {
foreach (var ext in extensions) {
filename = Path.Combine(path, file + ext);
if (File.Exists(filename)) {
return filename;
}
}
}
}
return null;
}
private static string[] GetExecutableExtensions(string file) {
var data = GetCmdOutput("echo %PATHEXT%");
var arr = data.TrimEnd('\n', '\r').Split(new [] {';'}, StringSplitOptions.RemoveEmptyEntries);
//If the command passed in ends with a executable extension then we dont need to test all extensions so set it to emtpy array
foreach (var ext in arr) {
if (file.EndsWith(ext, StringComparison.OrdinalIgnoreCase)) {
return new string[0];
}
}
return arr;
}
private static string[] GetPaths() {
var data = GetCmdOutput("echo %PATH%");
return data.TrimEnd('\n', '\r').Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
}
private static string GetCmdOutput(string cmd) {
using (var proc = new Process {
StartInfo = new ProcessStartInfo {
FileName = "cmd.exe",
Arguments = "/c " + cmd,
UseShellExecute = false,
RedirectStandardOutput = true,
CreateNoWindow = true
}
}) {
proc.Start();
return proc.StandardOutput.ReadToEnd();
}
}
}
Using user input into a textbox, I want to search for which file in the directory contains that text. I would then like to parse out the information
but I can't seem to find the string or at least return the information. Any help would be greatly appreciated.
My current code:
private void btnSearchSerial_Click(object sender, EventArgs e)
{
dynamic dirScanner = #"\\mypath\";
string strSerial;
string strSID;
string strInputLine;
string strOutput;
strSerial = Convert.ToString(txtSerialSearch);
strSID = Convert.ToString(txtSID);
if (txtSerialSearch.Text != "" && txtSID.Text != "")
{
try
{
string[] allFiles = Directory.GetFiles(dirScanner);
foreach (string file in allFiles)
{
if (file.EndsWith(".txt"))
{
using (StreamReader sr = new StreamReader(file))
{
while (sr.Peek() >= 0)
{
strInputLine = sr.ReadLine();
if (strInputLine.Contains(strSerial))
{
strOutput = Convert.ToString(strInputLine);
lblOutput.Text = Convert.ToString(strOutput);
}
}
}
}
}
}
}
}
You seem quite lost. Why are you using a dynamic when a string is all that you need? Your code has too many unnecessary variables and convertions. Here's a much simpler way to do it. I don't know what you want the label to have if there are many matching lines, here I'm only placing the first one there:
string dirScanner = #"\\mypath\";
if (string.IsNullOrWhiteSpace(txtSerialSearch.Text) || string.IsNullOrWhiteSpace(txtSID.Text))
return;
string[] allFiles = Directory.GetFiles(dirScanner, "*.txt");
foreach (string file in allFiles)
{
string[] lines = File.ReadAllLines(file);
string firstOccurrence = lines.FirstOrDefault(l => l.Contains(txtSerialSearch.Text));
if (firstOccurrence != null)
{
lblOutput.Text = firstOccurrence;
break;
}
}
I have implemented the same using Regular Expressions. You need to use namespace using System.Text.RegularExpressions;
string strSerial = #"Microsoft";
Regex match = new Regex(strSerial);
string matchinglines = string.Empty;
List<string> filenames = new List<string>(Directory.GetFiles(textBox1.Text));
foreach(string filename in filenames)
{
//StreamReader strFile = new StreamReader(filename);
string fileContent = File.ReadAllText(filename);
if(match.IsMatch(fileContent))
{
label1.Text = Regex.Match(fileContent, strSerial).ToString();
break;
}
}
Use System.LINQ:
var list_of_files_that_match = Directory.EnumerateFiles(dir).Where(delegate (string t)
{
return System.IO.File.ReadAllText(t).Contains(your_text);
}).ToList();
This worked for me. Quick and simple.
I wrote a text file. The first item of each line from this text file supposed to be key and rest of the items are values. My text file looks like this-
Flensburg;Nordertor;Naval Academy Mürwik;Flensburg Firth
Kiel;Laboe Naval Memorial;Zoological Museum of Kiel University;Kieler Förde
Lübeck;Holstentor;St. Mary's Church, Lübeck;Passat (ship);Burgtor;Lübeck Museum of Theatre Puppets;Trave
For my project purpose, I need to create .json data for each values and store those vales into the key name folder.As I am very new handling this situation I am not getting the correct logic to do this. However I tried in the follwing way by which I can create the key name folder and and only one subfolder into it. But I need to create all values folder inside the key folder. How can I do it.
My POI class from which I read the text file as key value is-
public class POI
{
Dictionary<string, List<string>> poi = new Dictionary<string, List<string>>();
public bool ContainsKey(string key) { return this.poi.ContainsKey(key); }
public List<string> GetValue(string key) { return this.poi[key]; }
public void POIList()
{
foreach (string line in File.ReadLines("POIList.txt"))
{
string[] parts = line.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
poi.Add(parts[0], new List<string>());
poi[parts[0]] = new List<string>(parts.Skip(1));
}
}
}
in the form1.cs
private void button1_Click(object sender, EventArgs e)
{
JSON_Output Json = new JSON_Output();
Json.ToJsonForLocation(comboBox1.Text);
}
also I set selectedindexchange from combobox2
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedItem != null)
{
POI poi1 = new POI();
poi1.POIList();
string txt = comboBox1.SelectedItem.ToString();
if (poi1.ContainsKey(txt))
{
List<string> points = poi1.GetValue(txt);
comboBox2.Items.Clear();
comboBox2.Items.AddRange(points.ToArray());
}
}
}
now where the json file generated to sore the value is-
public void ToJsonForLocation(string name)
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "Text_ImageWithHash");
string SubfolderName = Path.Combine(folderName, name);
//string folderName = Path.Combine(startPath, "Text_ImageWithHash");
System.IO.Directory.CreateDirectory(SubfolderName);
string fileName = name + ".json";
var path = Path.Combine(SubfolderName, fileName);
var Jpeg_File = new DirectoryInfo(startPath + #"\Image\" + name).GetFiles("*.jpg");
POIData Poi=new POIData();
Poi.Shorttext = File.ReadAllText(startPath + #"\Short Text\" + name + ".txt");
Poi.GeoCoordinates=GeosFromString(startPath + #"\Latitude Longitude\" + name + ".txt");
Poi.Images=new List<string> { Jpeg_File[0].Name};
string json = JsonConvert.SerializeObject(Poi,Formatting.Indented);
File.WriteAllText(path , json);
}
This is my code output while running the program.
after clicking button 1 Text_image_withHash folder is generated in the configuration directory.
Now if I open the folder I can see fthe following folders which is the key value from text file
After enable button 2 for combobox two the values folder is generated but not in the key folder.but as usual way in the Text_Image_withHash.
But What I want to do is-
To create that kind of folder-structure, simply use a foreach-loop. And String.Split.
Required usings:
using System;
using System.IO;
using System.Text;
using System.Linq;
Example:
// basePath can be anything
var basePath = "C:\Something";
// assume "info" is your CSV.
var infoParts = info.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (infoParts.Length == 0)
{
return;
}
var rootPath = infoParts[0];
Directory.CreateDirectory(Path.Combine(basePath, rootPath));
foreach (var subPath in infoParts.Skip(1))
{
Directory.CreateDirectory(Path.Combine(basePath, rootPath, subPath));
}
Saving JSON-files into these directories could then simply be made by combining the paths in a similar fashion.
I would also suggest some sanitizing of your paths (such as replacing '/' and '\\' with '_' or '-'.
Example implementation:
public void POIList()
{
foreach (string line in File.ReadLines("POIList.txt"))
{
string[] parts = line.Split(new[] { ';' },
StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0)
{
// Empty line or similar.
continue;
}
string cityName = parts[0];
poi.Add(cityName, new List<string>());
// Add the points of interest to local.
var points = new List<string>(parts.Skip(1));
poi[cityName] = points;
// basePath will have to be retrieved somehow. It's up to you.
string cityDirectoryPath = Path.Combine(basePath, cityName));
// Create a directory for the city.
Directory.CreateDirectory(cityDirectoryPath);
// Create sub-directories for points.
foreach (string point in points)
{
Directory.CreateDirectory(Path.Combine(
cityDirectoryPath, point));
}
}
}
I have just got my answer. This is the solution of the above question.
For POI Class :
public class POI
{
Dictionary<string, List<string>> poi = new Dictionary<string, List<string>>();
public bool ContainsKey(string key) { return this.poi.ContainsKey(key); }
public List<string> GetValue(string key) { return this.poi[key]; }
public void POIList()
{
foreach (string line in File.ReadLines("POIList.txt"))
{
string[] parts = line.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0)
{
// Empty line or similar.
continue;
}
string cityName = parts[0];
poi.Add(cityName, new List<string>());
// Add the points of interest to local.
var points = new List<string>(parts.Skip(1));
poi[cityName] = points;
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "FinalJson");
string cityDirectoryPath = Path.Combine(folderName, cityName);
Directory.CreateDirectory(cityDirectoryPath);
}
}
}
the the json output class
public void ToJsonForLocation(string CityName,string PoiName)
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "FinalJson");
string SubfolderName = Path.Combine(folderName, CityName);
System.IO.Directory.CreateDirectory(SubfolderName);
string fileName = PoiName + ".json";
var path = Path.Combine(SubfolderName, fileName);
var Jpeg_File = new DirectoryInfo(startPath + #"\Image\" + PoiName).GetFiles("*.jpg");
POIData Poi=new POIData();
Poi.Shorttext = File.ReadAllText(startPath + #"\Short Text\" + PoiName + ".txt");
Poi.GeoCoordinates = GeosFromString(startPath + #"\Latitude Longitude\" + PoiName + ".txt");
Poi.Images=new List<string> { Jpeg_File[0].Name};
string json = JsonConvert.SerializeObject(Poi,Formatting.Indented);
File.WriteAllText(path,json);
}
this is generated folder and file in this way-
The Final json file for all values
I'm having a bit of trouble passing this parameter to a class i have. Does anybody have any ideas?
Class 1's code:
public void DriveRecursion(string retPath)
{
//recurse through files. Let user press 'ok' to move onto next step
// string[] files = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
string pattern = " *[\\~#%&*{}/<>?|\"-]+ *";
//string replacement = "";
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
List<string> filePath = new List<string>();
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
if (regEx.IsMatch(fileNames))
{
string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
filePath.Add(fileNames);
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = fileNameOnly;
dataGridView1.Rows.Add(dgr);
\\I want to pass fileNames to my FileCleanup Method
\\I tried this:
\\SanitizeFileNames sf = new SanitizeFileNames();
\\sf.Add(fileNames); <-- this always gets an error..plus it is not an action i could find in intellisense
}
else
{
continue;
}
}
}
catch (Exception e)
{
StreamWriter sw = new StreamWriter(retPath + "ErrorLog.txt");
sw.Write(e);
}
}
Class 2's code:
public class SanitizeFileNames
{
public void FileCleanup(string fileNames)
{
string regPattern = " *[\\~#%&*{}/<>?|\"-]+ *";
string replacement = "";
Regex regExPattern = new Regex(regPattern);
}
What i want to do in SanitizeFileNames is do a foreach through the FileNames & FilePath and replace invalid chars (as defined in my Regex pattern). So, something along the lines of this:
using (StreamWriter sw = new StreamWriter(#"S:\File_Renames.txt"))
{
//Sanitize and remove invalid chars
foreach (string Files2 in filePath)
{
try
{
string filenameOnly = Path.GetFileName(Files2);
string pathOnly = Path.GetDirectoryName(Files2);
string sanitizedFilename = regEx.Replace(filenameOnly, replacement);
string sanitized = Path.Combine(pathOnly, sanitizedFilename);
sw.Write(sanitized + "\r\n");
System.IO.File.Move(Files2, sanitized);
}
//error logging
catch(Exception ex)
{
StreamWriter sw2 = new StreamWriter(#"S:\Error_Log.txt");
sw2.Write("ERROR LOG");
sw2.WriteLine(DateTime.Now.ToString() + ex + "\r\n");
sw2.Flush();
sw2.Close();
}
}
}
However, I'm having trouble passing the fileNames into my SanitizeFileNames class. Can anybody help me?
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
if (regEx.IsMatch(fileNames))
{
string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
filePath.Add(fileNames);
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = fileNameOnly;
dataGridView1.Rows.Add(dgr);
new SanitizeFileNames().FileCleanup(fileNames);
}
else
{
continue;
}
}
}
I suppose you want to pass a dirty name to the FileCleanup function and get a clean out. Here is how you can do that :
public String FileCleanup(string fileNames)
{
string regPattern = " *[\\~#%&*{}/<>?|\"-]+ *";
string replacement = "";
Regex regExPattern = new Regex(regPattern);
...
return cleanName;
}
and use it in your code like this:
String cleanName = new SanitizeFileNames().FileCleanup(fileNames);
where you put the comment.
You can create a third class static class and add static variable called files “public static List<string> Files= new List<string>()” as example.
When you create the files add the same files to the static variable.
When you clean the files loop throw the static variable, and at the end clear it.
The parameter type should be an enumerable collection of some sort: a list or an array would do. Also, strings are immutable so you could return a list of cleaned up filenames:
public class SanitizeFilenames
{
public List<string> FileCleanUp(IEnumerable<string> filenames)
{
var cleanedFileNames = new List<string>();
var invalidChars = Path.GetInvalidFileNameChars();
foreach(string file in filenames)
{
if(file.IndexOfAny(invalidChars) != -1)
{
// clean the file name and add it to the cleanedFileNames list
}
else
{
// nothing to clean here
cleanedFileNames.Add(file);
}
}
return cleanedFileNames;
}
}