File Path as Command Line Argument - c#

This is very common thing but i am very confused to get around this.
Taking file path as command line argument in c#.
If i give input "F:\\" then this works perfect.
But when i give input "F:\" it gives output like F:".
I know this is because of backslash escape character.
But my problem is how to get around this without modifying user input because logically user input is correct.
Is it possible without modifying user input get correct path in this situation?
I also know that there is # character which can be used.
But as i said this is command line argument so the string is already in variable.
I also read some blogs but still i remain unable to resolve my problem.
C# Command-Line Parsing of Quoted Paths and Avoiding Escape Characters
EDIT :Actually my program is to list all the files inside directory so i am first checking for Directory.Exists(command line arguments) and then getting list of all the files if directory exist.
Ok so in that case when user gives Command line argument as i shown above logically the drive exist but just because of escape character it returns false.
Just think about printing the command line argument as follow.
class Program
{
static void Main(string[] args)
{
Console.WriteLine("{0}", args[0]);
Console.Read();
}
}
I am having very less knowledge of c# thanks for helping.

Im not sure why your having a problem here. In M$ Windows, a directory can be specified with or without a back-slash so all of these are correct: c: and c:\ and c:\media and c:\media\. This is the same for Directory.Exists(path) and other functions like Directory.GetFiles(path).
Ths following is a very simple app to list directory files and in my environment it works regardless of whether I put a slash on the end. So c:\media\ gives me all my media files.
class Program
{
static void Main(string[] args)
{
string path = args[0];
Console.WriteLine("trying path: " + path);
if (Directory.Exists(path))
Directory.GetFiles(path).ToList().ForEach(s => Console.WriteLine(s));
else
Console.WriteLine("path not found");
}
}
One thing to note is that in visual studio, when using the debugger such as Quick Watch, it will show the escape character with backslashs. So if user enters c:\media\ the string will be stored as c:\media\ but when you quick watch the path in VS you'll see c:\\media\\; look deeper with the Text Visualisation feature and you'll see the path correctly shown as c:\media\.

You should use Path class and specifically Path.GetFullPath method to get correct full path.
class Program
{
static void Main(string[] args)
{
string path = Path.GetFullPath(args[0]);
Console.WriteLine("trying path: " + path);
if (Directory.Exists(path)){
var files = Directory.GetFiles(path);
foreach (var file in files) Console.WriteLine(file);
}
else
Console.WriteLine("path doesn't exist");
}
}
UPD. Paths with spaces should be passed in quotes. Or you should concat all your command line arguments, if path is the only input.

Use Environment.GetCommandLineArgs(). It will clean up the path.
See this link for more info: http://msdn.microsoft.com/en-us/library/system.environment.getcommandlineargs(v=vs.110).aspx

Well, if I understand correctly. You can use string.Format . There are overload methods that could help you without modifying much user input.
Sample code:
string[] inputs = ...
string output = string.Format("F:\\{0}\\{1}", inputs[0], inputs[1]);

C# interprets \ as an escape character. So \" is interpreted as "
Possible way to fix it (if you are sure that there is no " inside arguments:
string a = args[0].Replace('"', '\\');

I think your over thinking this. Logically that isnt valid input. \ is an escape character on the command prompt just as it is in c# inside of a string. What you have entered ("F:\") is an invalid value and it IS on the user to correct. The user is saying at this point that they want the quote.

Note that when you pass the filename in parameters, you need to have the access rights in the directory where file is placed, otherwise some parts of your application might fail unexpectedly and it might took you much time to figure out what's wrong there.
var args1 = Environment.GetCommandLineArgs().Skip(1);
if (args1 != null && args1.Count() > 0)
{
//do stuff
}

Related

Program that implements .CSV file data - Need assistance on implementing a Console.Readline() Method

I'm a novice programmer and I've recently written a C# program that implements .CSV file data which compiles correctly.
It functions perfectly and have met all but one of the requirements to complete this assignment.
The requirement is this:
"The program must allow me to pass a data-file name on the command line. If I pass the filename on the command line you must open that file for reading.(ie the .CSV file). "
I just don't understand how to implement a function that will be able to read the .CSV file on another desktop other than my own. I've been told that I would need to use the Console.Readline() Method but don't know where to start.
This is how I have it set in my current program:
class Program
{
static void Main(string[] args)
{
char choes;
bool file_test = true;
string file = "";
var key = ".";
{
file = #"C:\Users\BorusseGooner\desktop\projectData.csv";
Console.Clear();
Console.WriteLine();
StreamReader reader = new StreamReader(File.OpenRead(file));
This hard-coded path that will only work on my computer.
The receivables are:
1. The program.cs file
2. The .CSV
Any help would be greatly appreciated to revise my code to be able to be used & accessed on other computers.
"The program must allow me to pass a data-file name on the command line. If I pass the filename on the command line you must open that file for reading.(ie the .CSV file). "
This is knows as a command line argument, and has nothing to do with the Console.ReadLine() method.
Command line arguments are passed to your .Net executable using the args argument of the Main method.
If gives you the ability execute your program like this -
c:\>YourProgramName.exe CsvFilePathToOpen - where YourProgramName.exe is the name of your executable file and CsvFilePathToOpen is the path to the csv vile you want to open. Please note that since you're passing a path, you'll most likely need to wrap it with quotation marks, since it will most likely contain characters that can mess it up (like spaces, for instance) - so it should look like this:
c:\>YourProgramName.exe "d:\Some folder\ some file.csv"
In your code, you should check the length of the args argument, and if it has a length of at least 1, you should try to use it's content as the path, instead of the hard coded one:
static void Main(string[] args)
{
char choes;
bool file_test = true;
string file = args.Length > 0: args[0] : #"C:\Users\BorusseGooner\desktop\projectData.csv";
var key = ".";
//... rest of the code here...

Unhandled DirectoryNotFound exception thrown using DirectoryInfo.EnumerateFiles and "subst" command

Background:
I'm trying to write a little program that recursively goes through all files contained in a user specified folder (and all its subfolders). The program is supposed to check the size of each file and if it matches a user defined value, copy their full path (File.FullName) to a text box control I've setup on the only form of the program.
The trouble is that because of the intended use of the program (working with recovered files and folders from damaged partitions on external drives), often the path length goes well over the maximum path length limit. In order to marginally circumvent this I decided to map the user selected starting directory to a virtual drive using the Win32 command line function "subst".
Incriminated Code:
private void button1_Click(object sender, EventArgs e)
{
if (txtboxSizeFilter.Text != "")//code will execute only if a size filter has been provided by the user
{
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
List<char> driveLetters = new List<char>(26); // Allocate space for alphabet
for (int i = 65; i < 91; i++) // increment from ASCII values for A-Z
{
driveLetters.Add(Convert.ToChar(i)); // Add uppercase letters to possible drive letters
}
foreach (string drive in Directory.GetLogicalDrives())
{
driveLetters.Remove(drive[0]); // removed used drive letters from possible drive letters
}
GlobalVars.Drive = driveLetters[0].ToString() + ":"; //gets the next available drive letter to be used as the virtual drive and adds a convenient ":" at the end
string command = "subst " + GlobalVars.Drive + " " + "\"" + folderBrowserDialog1.SelectedPath.ToString() + "\""; //command to be passed to "cmd". Ex. Content= subst J: "C:\users\someuser\somelongnamefolder\some longer name folder with spaces"
System.Diagnostics.Process.Start("cmd.exe", #"/c " + command);//launches the command prompt and initiates subst. This section has been tested and works fine.
DirectoryInfo DI = new DirectoryInfo(GlobalVars.Drive);//here i start at the drive letter that points to the desired directory.
foreach (var fi in DI.EnumerateFiles("*", SearchOption.AllDirectories))//searches for any file in all dirs. THE EXCEPTION "DirectoryNotFound" OBJECT OF THIS QUESTION IS THROWN EXACTLY HERE.
{
try //I need this because I might throw a PathTooLongException despite my use of subst
{
if (fi.Length == Convert.ToInt64(txtboxSizeFilter.Text))//if the size of the file is = to target size then I add the full path name to the textbox along with its actual size (for debug purposes only).
{
txtboxResults2Confirm.Text = txtboxResults2Confirm.Text + fi.FullName.ToString() + "_" + fi.Length.ToString() + Environment.NewLine;
}
}
catch (PathTooLongException)//if the path is too long, indicate it with the codeword "SKIP"
{
txtboxResults2Confirm.Text = txtboxResults2Confirm.Text + "SKIP" + Environment.NewLine;
}
}
btnConfirm.Enabled = true;//enables the other button on the form that will actually delete the files.
}
}
else
{
MessageBox.Show("INPUT SIZE FIRST!");
}
}
Problem/Research/Question:
As specified in the comments and the tile, an unhandled DirectoryNotFound exception occurs at the second foreach statement (as indicated by the IDE, Microsoft Visual Studio Ultimate 2013). Doing a step by step debug indicates that the foreach loop actually works for a while and then "randomly" throws the exception. I was able to verify that it goes through all the files in the root directory and at least a large part of the first subdirectory without any trouble at all (because of the large amount of files/subdirectories I wasn't able to pinpoint where exactly the failure occurs). The error states that the directory not found is the root one (so, to follow the example in the comments: "Unable to find J:\"). I've tried to follow the first catch with another to handle the DirectoryNotFound exception to not avail, which makes sense since the exception seems to originate directly in the foreach statement. I've also tried to wrap the entire foreach statement into a try-catch framework without any luck. Finally, getting rid of the whole "subst" section and just working with the user selected path produces no such error.
My question is, why is the exception thrown? And why am I not able to handle it in any way? Is there an alternate approach to this problem that would ensure the avoidance of the DirectoryNotFound exception?
The Process.Start does exactly that: it starts a new process (with its own main thread, etc etc) which may or may not complete by the time your next line of code in the original program executes. A couple of ways to resolve this: a) call DefineDosDevice which will mean the "subst" command runs in the current program thread, or b) grab the pipe to the cmd process and listen on it for completion. Both are of intermediate difficulty, pick your poison.
Of course, the exception that you're experiencing is because the subst command didn't complete in time when the code to enumerate the (yet un-aliased) directory executes.

how do i get the application name from the default value in Registry/LocalMachine/Software/Classes/.docx/shell/Open/Command

i would need to know the most effective way get the name of the application from the Registry/LocalMachine/Software/Classes/.docx/shell/Open/Command . for example from this
"C:\Program Files (x86)\Microsoft Office\Office15\POWERPNT.EXE" "%1" /ou "%u"
i would need only the 'POWERPNT.EXE'. substring and replace is not effective as the value inside appears differently. for example
"C:\Program Files (x86)\Microsoft Office\Office15\EXCEL.EXE" /dde
"C:\Program Files (x86)\Skype\Phone\Skype.exe" "/uri:%l"
the real problem that i'm encountering here is that the string that i'm retrieving may contain command-line arguments as well as the path to the executable for which substring and replace would not be helpful anymore.
the intention of my method is to find out the program being used to open associated file type and then using the Process.Start("EXCEL.EXE", fileURL) to open a file from a SharePoint DocumentLibrary
Would something like this work?
public static string GetFileName(string input)
{
int extensionIndex = input.IndexOf(".exe", StringComparison.OrdinalIgnoreCase);
if (extensionIndex < 0) return string.Empty;
return Path.GetFileName(input.Replace("\"", "").Substring(0, extensionIndex + 4));
}
// Or, if you want to get the full path:
public static string GetFilePath(string input)
{
int extensionIndex = input.IndexOf(".exe", StringComparison.OrdinalIgnoreCase);
if (extensionIndex < 0) return string.Empty;
return input.Replace("\"", "").Substring(0, extensionIndex + 4);
}
Usage:
string regValue =
"C:\\Program Files (x86)\\Microsoft Office\\Office15\\EXCEL.EXE /dde";
Console.WriteLine(GetFileName(regValue));
Console.WriteLine(GetFilePath(regValue));
// Output:
// EXCEL.EXE
// C:\Program Files (x86)\Microsoft Office\Office15\EXCEL.EXE
regValue = "\"C:\\Program Files (x86)\\Skype\\Phone\\Skype.exe\" \"/uri:%l\"";
Console.WriteLine(GetFileName(regValue));
Console.WriteLine(GetFilePath(regValue));
// Output:
// Skype.exe
// C:\Program Files (x86)\Skype\Phone\Skype.exe
In almost all cases, CommandLineToArgvW should work nicely. It returns an array of strings, the first element of which is the path to the executable.
Then all you need to do is remove the quote marks (if any) and everything up to the last backslash.
There may (or may not) be pathological cases in which this function does not interpret the string the same way as Explorer does. I don't think there's any way to determine this other than by experimentation.
The comments to initial question clarify the actual problem.
the intention of my method is to find out the program being used to
open associated file type and then using the
Process.Start("EXCEL.EXE", fileURL) to open the file
If all you need is to open a given file in associated application, you don't need to read the Registry, or parse the command line.
You can open file by calling a different overload of Process.Start that takes one parameter.
Process.Start(fileURL);
According to MSDN: http://msdn.microsoft.com/en-us/library/53ezey2s(v=vs.110).aspx, parameter is the name of a document or application file to run in the process.
I tested both local file, like "C:\folder\test.txt", and URLs.
Process.Start(#"C:\folder\test.txt"); // Opens test.txt in Notepad
and
Process.Start("http://regmagik.com/index.htm"); // Opens web page in the browser

"Could not find a part of the path" error message

I am programming in c# and want to copy a folder with subfolders from a flash disk to startup.
Here is my code:
private void copyBat()
{
try
{
string source_dir = "E:\\Debug\\VipBat";
string destination_dir = "C:\\Users\\pc\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup";
if (!System.IO.Directory.Exists(destination_dir))
{
System.IO.Directory.CreateDirectory(destination_dir);
}
// Create subdirectory structure in destination
foreach (string dir in Directory.GetDirectories(source_dir, "*", System.IO.SearchOption.AllDirectories))
{
Directory.CreateDirectory(destination_dir + dir.Substring(source_dir.Length));
}
foreach (string file_name in Directory.GetFiles(source_dir, "*.*", System.IO.SearchOption.AllDirectories))
{
File.Copy(file_name, destination_dir + file_name.Substring(source_dir.Length), true);
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "HATA", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
I got an error:
Could not find a part of the path E:\Debug\VipBat
The path you are trying to access is not present.
string source_dir = "E:\\Debug\\VipBat\\{0}";
I'm sure that this is not the correct path. Debug folder directly in E: drive looks wrong to me. I guess there must be the project name folder directory present.
Second thing; what is {0} in your string. I am sure that it is an argument placeholder because folder name cannot contains {0} such name. So you need to use String.Format() to replace the actual value.
string source_dir = String.Format("E:\\Debug\\VipBat\\{0}",variableName);
But first check the path existence that you are trying to access.
There's something wrong. You have written:
string source_dir = #"E:\\Debug\\VipBat\\{0}";
and the error was
Could not find a part of the path E\Debug\VCCSBat
This is not the same directory.
In your code there's a problem, you have to use:
string source_dir = #"E:\Debug\VipBat"; // remove {0} and the \\ if using #
or
string source_dir = "E:\\Debug\\VipBat"; // remove {0} and the # if using \\
Is the drive E a mapped drive? Then, it can be created by another account other than the user account. This may be the cause of the error.
I had the same error, although in my case the problem was with the formatting of the DESTINATION path. The comments above are correct with respect to debugging the path string formatting, but there seems to be a bug in the File.Copy exception reporting where it still throws back the SOURCE path instead of the DESTINATION path. So don't forget to look here as well.
-TC
Probably unrelated, but consider using Path.Combine instead of destination_dir + dir.Substring(...). From the look of it, your .Substring() will leave a backlash at the beginning, but the helper classes like Path are there for a reason.
There can be one of the two cause for this error:
Path is not correct - but it is less likely as CreateDirectory should create any path unless path itself is not valid, read invalid characters
Account through which your application is running don't have rights to create directory at path location, like if you are trying to create directory on shared drive with not enough privileges etc
File.Copy(file_name, destination_dir + file_name.Substring(source_dir.Length), true);
This line has the error because what the code expected is the directory name + file name, not the file name.
This is the correct one
File.Copy(source_dir + file_name, destination_dir + file_name.Substring(source_dir.Length), true);
We just had this error message occur because the full path was greater than 260 characters -- the Windows limit for a path and file name. The error message is misleading in this case, but shortening the path solved it for us, if that's an option.
I resolved a similar issue by simply restarting Visual Studio with admin rights.
The problem was because it couldn't open one project related to Sharepoint without elevated access.
This could also be the issue: Space in the folder name
Example:
Let this be your path:
string source_dir = #"E:\Debug\VipBat";
If you try accessing this location without trying to check if directory exists, and just in case the directory had a space at the end, like :
"VipBat    ", instead of just "VipBat" the space at the end will not be visible when you see in the file explorer.
So make sure you got the correct folder name and dont add spaces to folder names. And a best practice is to check if folder exists before you keep the file there.

move zip file using file.copy()

I am trying to move a file from server \\abc\\C$\\temp\\coll.zip to another server
\\def\\c$\\temp.
I am trying to use File.Copy(source,destination).
But I am getting the error in source path saying: Couldn't find the part of the path.
I am not sure what is wrong with the source path.
You could use a C# # Verbatim and also use checks in the code like this:
string source = #"\\abc\C$\temp\coll.zip";
string destination = #"\\def\c$\temp\coll.zip";
string destDirectory = Path.GetDirectoryName(destination)
if (File.Exists(source) && Directory.Exists(destDirectory)) {
File.Copy(source, destination);
}
else {
// Throw error or alert
}
Make sure that your "\" characters are escaped if you are using C#. You have to double the backslashes or prefix the string literal with #, like this:
string fileName = #"\\abc\C$\temp\coll.zip";
or
string fileName = "\\\\abc\\C$\\temp\\coll.zip";
looks like you need two backslashes at the beginning:
\\abc\C$\temp\coll.zip
\\def\c$\temp
Make sure you are using a valid UNC Path. UNC paths should start with \ not just . You should also consider using System.IO.File.Exists(filename); before attempting the copy so you can avoid the exception altogether and so your app can handle the missing file gracefully.
Hope this helps
It could be the string you are using for the path. If it is exactly as you have entered here I believe you need double backslashes. "\\" before the server name.
I always use network shares for that kind of work, but UNC path's should be available too.
Don't forget that you need to escape your string when you use \'s. Also, UNC paths most of the time start with a double .
Example:
\\MyComputerName\C$\temp\temp.zip
Actually I missed # before the two strings.The source and the destination path.
That is why it was giving error.

Categories

Resources