I need to retrieve paths of files and folders currently copied into the clipboard, is this possible in C#?
So let's say I do Ctrl + C a folder. That folder will go to clipboard, I need a way to extract the path to that folder. Same goes for copied files.
I'm developing a file server, I already can send files and folders: all I need is to provide a list of paths to the function.
Microsoft supplies some samples about it:
Have a look at: DragDropOpenTextFile
This is the method used to check it there is a file copied in the clipboard:
// If the data object in args is a single file, this method will return the filename.
// Otherwise, it returns null.
private string IsSingleFile(DragEventArgs args)
{
// Check for files in the hovering data object.
if (args.Data.GetDataPresent(DataFormats.FileDrop, true))
{
var fileNames = args.Data.GetData(DataFormats.FileDrop, true) as string[];
// Check for a single file or folder.
if (fileNames?.Length is 1)
{
// Check for a file (a directory will return false).
if (File.Exists(fileNames[0]))
{
// At this point we know there is a single file.
return fileNames[0];
}
}
}
return null;
}
You get a DragEventArgs from the Drop event handler of your control.
private void EhDrop(object sender, DragEventArgs args)
{
// Mark the event as handled, so Control's native Drop handler is not called.
args.Handled = true;
var fileName = IsSingleFile(args);
if (fileName != null)
{
// Do something.
}
}
Ok got it to work myself, Clipboard.GetFileDropList() gets you both files and folders paths, what a neat little function!
var unparsedFilesList = Clipboard.GetFileDropList();
foreach(var filePath in unparsedFilesList)
{
MessageBox.Show(filePath);
}
Related
I need to convert images(like .jpg) to PDF files for an assignment for school. I have a ListBox where I put the pages of the PDF file, so the user can reorder the list and convert the files in that order.
I have the files in a temporary folder in order to get the files there to convert them to PDF.
My problem here is : how do I convert the files with the order that the user had chosen?
I already searched and I tried to do a Class with the strings ID and Name so i get the ID from the item in the ListBox and change it on a new list. And i think after, I do a foreach() loop where I get the files from the temporary folder and merge them in a new PDF file, but to do in the order I want, I think I have to compare the name of the file with the name in the list and, if it matches, convert and add it, if not, pass to the next file.
But I don't know how to do it.
Can please someone help me getting this right?
Thanks in advance!
I'm sending my code to:
//the open files button
private void proc2_Click(object sender, EventArgs e)
{
OpenFileDialog dialogo = new OpenFileDialog();
dialogo.Title = "Search files";
dialogo.InitialDirectory = #"E:\";
dialogo.Filter = "Images (.bmp,.jpg,.png,.tiff,.tif) |*.bmp;*.jpg;*.png;*tiff;*tif|All of the files (*.*)|*.*";
DialogResult resposta = dialogo.ShowDialog();
if (resposta == DialogResult.OK)
{
string caminhoCompleto = dialogo.FileName;
caminho2 = dialogo.SafeFileName;
caminhotb2.Text = caminhoCompleto;
string fish = "";
string path = #"C:\temporario";
if(Directory.Exists(path))
{
fish=Path.Combine(path, caminho2);
}
else
{
Directory.CreateDirectory(path);
fish = Path.Combine(path, caminho2);
}
File.Create(fish);
listaimg.Items.Add(caminho2);
}
}
public string[] GetFilesImg4() //jpg files
{
if (!Directory.Exists(#"C:\temporario"))
{
Directory.CreateDirectory(#"C:\temporario");
}
DirectoryInfo dirInfo = new DirectoryInfo(#"C:\temporario");
FileInfo[] fileInfos4 = dirInfo.GetFiles("*.jpg");
foreach (FileInfo info in fileInfos4)
{
if (info.Name.IndexOf("protected") == -1)
list4.Add(info.FullName);
}
return (string[])list4.ToArray(typeof(string));
}
If both actions happen in the same process, you can just store the list of file names in memory (and you already do add them to listaimg):
public string[] GetFilesImg4() //jpg files
{
string tempPath = #"C:\temporario";
if (!Directory.Exists(tempPath))
{
foreach (string filename in listimga.Items)
{
if (!filename.Contains("protected"))
list4.Add(Path.Combine(tempPath, filename);
}
}
return (string[])list4.ToArray(typeof(string));
}
if these are different processes then you can just dump content of your listimga at some point and then read it from the same file. In the example below I store it to file named "order.txt" in the same directory, but logic may be more complicated, such as merging several files with a timestamp and such.
// somewhere in after selecting all files
File.WriteAllLines(#"c:\temporario\order.txt", listimga.Items.Select(t=>t.ToString()));
public string[] GetFilesImg4() //jpg files
{
string tempPath = #"C:\temporario";
if (!Directory.Exists(tempPath))
{
var orderedFilenames = File.ReadAllLines(Path.Combine(tempPath, "order.txt")); // list of files loaded in order
foreach (string filename in orderedFilenames)
{
if (!filename.Contains("protected"))
list4.Add(Path.Combine(tempPath, filename);
}
}
return (string[])list4.ToArray(typeof(string));
}
it's also a good idea to examine available method on a class, such as in this case string.IndexOf(s) == -1 is equivalent to !string.Contains(s) and the latter is much more readable at least for an English speaking person.
I also noticed that your users have to select documents one by one, but FileOpen dialogs allow to select multiple files at a time, and I believe it preserves the order of selection as well.
If order of selection is important and file open dialogs don't preserve order or users find it hard to follow you can still use multiple file selection open dialog and then allow to reorder your listimga list box to get the order right.
I'm trying to load a picture into a pictureBox from a string array of pictures I created using Directory.GetFiles(). I believe I am not setting properly setting the picFile correctly.
I've than created a pictureBox_Click event to load subsequent pictures but have not written that event handler
string fileEntries = "";
private void showButton_Click(object sender, EventArgs e)
{
// First I want the user to be able to browse to and select a
// folder that the user wants to view pictures in
string folderPath = "";
FolderBrowserDialog folderBrowserDialog1 = new FolderBrowserDialog();
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
folderPath = folderBrowserDialog1.SelectedPath;
}
// Now I want to read all of the files of a given type into a
// array that from the path provided above
ProcessDirectory(folderPath);
// after getting the list of path//filenames I want to load the first image here
string picFile = fileEntries;
pictureBox1.Load(picFile);
}
public static void ProcessDirectory(string targetDirectoy)
{
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(targetDirectoy);
}
// event handler here that advances to the next picture in the list
// upon clicking
}
If I redirect the string array to the Console I see the list of files in that directory but it also has the full path as part of the string - not sure if that is the issue.
string[] fileEntries = ProcessDirectory(folderPath);
if (fileEntries.Length > 0) {
string picFile = fileEntries[0];
pictureBox1.Load(picFile);
}
You have fileEntries declared twice.
public static string[] ProcessDirectory(string targetDirectoy) {
return Directory.GetFiles(targetDirectoy);
}
Now I want to read all of the files of a given type into a
array that from the path provided above
So you have to change the signature of the method ProcessDirectory to return a string affy that includes all the picture files, you can use the search pattern to get files with specific extension as well. You can use the following signature:
public static string[] ProcessDirectory(string targetDirectoy)
{
return Directory.GetFiles(targetDirectoy,"*.png");
}
after getting the list of path//filenames I want to load the first image here
So you can call the method to get all files in that specific directory with specific extensions. And then load the first file to the picturebox if the array having any files, you can use the following code for this:
var pictureFiles = ProcessDirectory(folderPath);
if (pictureFiles.Length > 0)
{
// process your operations here
pictureBox1.Load(pictureFiles[0]);
}
Okay, I have a button (button1) which I want to copy the static directory to the chosen directory. Essentially I have textbox1 in which different numeric values are added which correlate with different directories. I have a dictionary that sets the string to mapping which links to codes from textbox2 to the path of the origination folder. . This determines where we copy our data from. I want this data to then be copied into the folder selected in textbox2 through the folderBrowserDialog1.ShowDialog(); command. how to i create the dictionary and where do i put it for textbox1, and how do i then get the button to take whatever is in textbox1 and copy the entire directory to textbox2?
private Dictionary<string, string> mapping = new Dictionary<string, string>
{
{ "111", #"C:\Program Files\Example" },
{ "112", #"C:\Program Files\Example2" },
{ "113", #"C:\Program Files\Example3" },
};
public static string[] GetFiles(string mapping);
public static void Copy(string sourceFileName, string destFileName);
private void button2_Click(object sender, EventArgs e)
{
string destination = textBox1.Text;
foreach (var f in Directory.GetFiles(mapping))
{
File.Copy(Path.Combine(mapping, f)); destination;
}
}
Here is an answeer to "How copy an entire directory of files":
Use Directory.GetFiles() (see documentation) to get a list of all files in a directory.
Then use File.Copy() (see documenation) to copy a single file:
foreach(var f in Directory.GetFiles(srcPath))
{
File.Copy(Path.Combine(srcPath, f), dstPath);
}
EDIT
Directory.GetFiles() requires a path:
private void button2_Click(object sender, EventArgs e)
{
string destination = textBox1.Text;
string srcdir = mapping["111"];
foreach(var f in Directory.GetFiles(srcdir))
{
string srcpath = Path.Combine(srcdir, f)
File.Copy(srcpath, destination);
}
}
I'm not 100% sure I understood the details of your question, as the uses of TextBox1 and TextBox2 don't seem consistent, but here's what I read:
TextBox1 has the codes that the dictionary maps to a source directory.
TextBox2 has the path (from the dialog box) to the destination directory.
If that is correct, you're close. Some things to note:
I'm not sure why you have these two lines. They look like method definitions, but there's no implementation. I think you can remove them and use the equivalent System.IO calls:
public static string[] GetFiles(string mapping);
public static void Copy(string sourceFileName, string destFileName);
Directory.GetFiles(mapping) won't work, because mapping is a Dictionary<string, string>, not a string. You need to select the corresponding value (path) based on the key (numeric code) from TextBox1 and use that in the Directory.GetFiles() method.
File.Copy(Path.Combine(mapping, f)); destination; is an incorrect syntax and won't compile (should be File.Copy(Path.Combine(mapping, f), destination);. Additionally, you don't need to combine the source path and filename for the first argument, as GetFiles returns the path along with the filename (including extension). You will need to get the filename alone and combine it with the sourece path for the destination file, however. You can use Path.GetFileName to do this.
Try this code below - it addresses the issues noted above, with the assumption being that textBox1 is the source in mappings and textBox2 is the destination from the dialog window:
private void button2_Click(object sender, EventArgs e)
{
string source = textBox1.Text
string destination = textBox2.Text;
if (mappings.ContainsKey(source))
{
foreach (var f in Directory.GetFiles(source))
{
File.Copy(f, Path.Combine(destination, Path.GetFileName(f)));
}
}
else
{
// No key was found, how you handle it will be dictated by the needs of the application and/or users.
}
}
The above code does the following:
Gets the numeric value for the path of the source directory. This should correspond to one of the keys in the dictionary.
Gets the path for the destination directory based on the user selected value from the dialog box.
Checks to see if the key from textBox1 is present in the directory.
If it is, it gets the corresponding value for that key, which is the path for the source directory.
Next, it loops through the files in the specified source directory, copying each one in turn to the destination directory. Note that f (the file) is used as the source file for the first argument (as it contains the path as well, as Directory.GetFiles() returns both the path and the filename), and the destination directory is combined with the filename (retrieved by a call to Path.GetFileName). If f alone was used in the Path.Combine() method, you'd wind up with sourcePath\originalPath\filename.
If the key wasn't found, you ignore it or do something with it.
Again, the above code is based on my understanding of your question. If my understanding was less than correct, the principles I outlined should still be able to assist you in resolving the issue.
** EDIT **
Per the comments below, it sounds like all you need to do is flip the assignments for source and destination. textBox2 will contain the code that corresponds to a key in the mappings directory, which will give you the path of the source directory. textBox1 will contain the destination path. Like this:
string source = textBox2.Text
string destination = textBox1.Text;
The rest of the code stays the same.
I want to move a directory from one location to another using C# .NET. I used Directory.Move or even DirectoryInfo (with MoveTo) this simple way:
// source is: "C:\Songs\Elvis my Man"
// newLocation is: "C:\Songs\Elvis"
try
{
// Previous command was: Directory.Move(source, newLocation);
DirectoryInfo dir = new DirectoryInfo(source);
dir.MoveTo(newLocation);
}
catch (Exception e)
{
Console.WriteLine("Error: "+ e.Message);
}
But action that's being done (for both cases) is renaming the folder name from 'source' to 'newLocation'
What I expected? that folder "Elvis my man" will be now in "Elvis" folder.
What has happened? "Elvis my man" was changed to "Elvis" (Renamed). If the directory "Elvis" is already exists, it can't change it to "Elvis" (cause he can't make a duplicate names), therefore I get an exception saying that.
What am I doing wrong??
Many thanks!!!
I would advise putting validation around the Move command to ensure that the source location does exists and the destination location doesn't exists.
I've always found it easier to avoid the exceptions than handle them once they do occur.
You'll probably want to include exception handling as well, just in case the access permissions are a problem or a file is open and can't be moved...
Here's some sample code for you:
string sourceDir = #"c:\test";
string destinationDir = #"c:\test1";
try
{
// Ensure the source directory exists
if (Directory.Exists(sourceDir) == true )
{
// Ensure the destination directory doesn't already exist
if (Directory.Exists(destinationDir) == false)
{
// Perform the move
Directory.Move(sourceDir, destinationDir);
}
else
{
// Could provide the user the option to delete the existing directory
// before moving the source directory
}
}
else
{
// Do something about the source directory not existing
}
}
catch (Exception)
{
// TODO: Handle the exception that has been thrown
}
Even though this works in the command line to move a file, when programming you need to provide the full new name.
So you'd need to change newLocation to "C:\Songs\Elvis\Elvis my Man" to make this work.
From MSDN,
This method throws an IOException if, for example, you try to move c:\mydir to c:\public, and c:\public already exists. You must specify "c:\public\mydir" as the destDirName parameter, or specify a new directory name such as "c:\newdir".
It looks like you need to set newLocation to C:\Songs\Elvis\Elvis my man
private void moveDirectory(string fuente,string destino)
{
if (!System.IO.Directory.Exists(destino))
{
System.IO.Directory.CreateDirectory(destino);
}
String[] files = Directory.GetFiles(fuente);
String[] directories = Directory.GetDirectories(fuente);
foreach (string s in files)
{
System.IO.File.Copy(s, Path.Combine(destino,Path.GetFileName(s)), true);
}
foreach(string d in directories)
{
moveDirectory(Path.Combine(fuente, Path.GetFileName(d)), Path.Combine(destino, Path.GetFileName(d)));
}
}
Imagine I wish to create (or overwrite) the following file :- C:\Temp\Bar\Foo\Test.txt
Using the File.Create(..) method, this can do it.
BUT, if I don't have either one of the following folders (from that example path, above)
Temp
Bar
Foo
then I get an DirectoryNotFoundException thrown.
So .. given a path, how can we recursively create all the folders necessary to create the file .. for that path? If Temp or Bar folders exists, but Foo doesn't... then that is created also.
For simplicity, lets assume there's no Security concerns -- all permissions are fine, etc.
To summarize what has been commented in other answers:
//path = #"C:\Temp\Bar\Foo\Test.txt";
Directory.CreateDirectory(Path.GetDirectoryName(path));
Directory.CreateDirectory will create the directories recursively and if the directory already exist it will return without an error.
If there happened to be a file Foo at C:\Temp\Bar\Foo an exception will be thrown.
DirectoryInfo di = Directory.CreateDirectory(path);
Console.WriteLine("The directory was created successfully at {0}.",
Directory.GetCreationTime(path));
See this MSDN page.
Use Directory.CreateDirectory before you create the file. It creates the folder recursively for you.
. given a path, how can we recursively create all the folders necessary to create the file .. for that path
Creates all directories and subdirectories as specified by path.
Directory.CreateDirectory(path);
then you may create a file.
You will need to check both parts of the path (directory and filename) and create each if it does not exist.
Use File.Exists and Directory.Exists to find out whether they exist. Directory.CreateDirectory will create the whole path for you, so you only ever need to call that once if the directory does not exist, then simply create the file.
You should use Directory.CreateDirectory.
http://msdn.microsoft.com/en-us/library/54a0at6s.aspx
Assuming that your assembly/exe has FileIO permission is itself, well is not right. Your application may not run with admin rights. Its important to consider Code Access Security and requesting permissions
Sample code:
FileIOPermission f2 = new FileIOPermission(FileIOPermissionAccess.Read, "C:\\test_r");
f2.AddPathList(FileIOPermissionAccess.Write | FileIOPermissionAccess.Read, "C:\\example\\out.txt");
try
{
f2.Demand();
}
catch (SecurityException s)
{
Console.WriteLine(s.Message);
}
Understanding .NET Code Access Security
Is “Code Access Security” of any real world use?
You want Directory.CreateDirectory()
Here is a class I use (converted to C#) that if you pass it a source directory and a destination it will copy all of the files and sub-folders of that directory to your destination:
using System.IO;
public class copyTemplateFiles
{
public static bool Copy(string Source, string destination)
{
try {
string[] Files = null;
if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
destination += Path.DirectorySeparatorChar;
}
if (!Directory.Exists(destination)) {
Directory.CreateDirectory(destination);
}
Files = Directory.GetFileSystemEntries(Source);
foreach (string Element in Files) {
// Sub directories
if (Directory.Exists(Element)) {
copyDirectory(Element, destination + Path.GetFileName(Element));
} else {
// Files in directory
File.Copy(Element, destination + Path.GetFileName(Element), true);
}
}
} catch (Exception ex) {
return false;
}
return true;
}
private static void copyDirectory(string Source, string destination)
{
string[] Files = null;
if (destination[destination.Length - 1] != Path.DirectorySeparatorChar) {
destination += Path.DirectorySeparatorChar;
}
if (!Directory.Exists(destination)) {
Directory.CreateDirectory(destination);
}
Files = Directory.GetFileSystemEntries(Source);
foreach (string Element in Files) {
// Sub directories
if (Directory.Exists(Element)) {
copyDirectory(Element, destination + Path.GetFileName(Element));
} else {
// Files in directory
File.Copy(Element, destination + Path.GetFileName(Element), true);
}
}
}
}
Following code will create directories (if not exists) & then copy files.
// using System.IO;
// for ex. if you want to copy files from D:\A\ to D:\B\
foreach (var f in Directory.GetFiles(#"D:\A\", "*.*", SearchOption.AllDirectories))
{
var fi = new FileInfo(f);
var di = new DirectoryInfo(fi.DirectoryName);
// you can filter files here
if (fi.Name.Contains("FILTER")
{
if (!Directory.Exists(di.FullName.Replace("A", "B"))
{
Directory.CreateDirectory(di.FullName.Replace("A", "B"));
File.Copy(fi.FullName, fi.FullName.Replace("A", "B"));
}
}
}