I'm trying to use the Duplicati API to restore a single file.
About the Scenario: The whole thing runs on linux so it is compiled with mono. My backup contains two source Folders, so if I run Interface.ListSourceFolders() I get an Array of two.
Desired result: I want to restore one single file (or Folder) from my backup
Current result: If I run the code below it restores all the backed up files (so Folder 1 and Folder 2) into the path in //Comment1.
List<string> files = new List<string>();
files.Add("path"); //Comment1
Dictionary<string,string> options = new Dictionary<string,string>();
options["passphrase"] = MySettings.Password;
options["restore-time"] = date;
//Comment2
Interface i = new Interface("file:///path/to/archives", options);
string result = i.Restore(files.ToArray());
What I tried: I tried to set the path at //Comment1 to the absolute path (/desired/file/to/restore) or using the index of the source Folder (0/file/to/restore) and I also played around at //Comment2. e.g. I added something like options["restore-path"] = "/path/to/restore". I always get the same result.
Does anyone see what I'm doing wrong? Because I don't know what else I could try. There is almost no documentation so I don't know where to search. If someone knows a link for a good documentation I would be happy too!
In case if someone is interested. After trying around for hours I finally found out how to restore just a single file or folder. Here is what I'm doing now:
List<string> files = new List<string>();
files.Add("/restore/path"); //Comment1
Dictionary<string,string> options = new Dictionary<string,string>();
options["passphrase"] = MySettings.Password;
options["restore-time"] = date;
options["file-to-restore"] = "files"; //Comment2
Interface i = new Interface("file:///path/to/archives", options);
string result = i.Restore(files.ToArray());
At //Comment1 you need to set the desired restore path. In this folder all backup-set-folders are created (The folders from Interface.ListSourceFolders())
At //Comment2 you can specify the files to be restored in this form: 0/file/to/restore where 0 is the index of the source folder (Interface.ListSourceFolders()). If you need to restore multiple files you can do it by combining them into one string: e.g. Windows: 0/file1;1/file2 or Linux 0/file1:1/file2 (The difference is semicolon or colon)
Now there is just one more thing: You can not restore a folder with its files. You need to combine all files and sub-files in the string mentioned above.
I hope I could help somebody.
Related
For my work I have a varying list of appsettings.json files for different iterations of the same project. I have created a WinFormApp that has a series of buttons that basically copy the selected json file contents to my clipboard for me to then paste into the appsettings file for my project.
Every value in these settings files stays the same apart from one which we update on a monthly basis, I wrote some code that takes a text value entered on the form and updates this value into the Json files and then saves them.
private void UpdateNativeAppPaths(string newPath, string device)
{
var currentDirectory = Directory.GetCurrentDirectory();
var appSettingsFilesRoot =
Path.GetFullPath(Path.Combine(currentDirectory, "..", "..", "..", "AppSettingsFiles"));
var appSettingsPathsList = Directory.GetFiles(appSettingsFilesRoot, "*.*", SearchOption.AllDirectories);
foreach (var path in appSettingsPathsList.Where(path => path.EndsWith($"{device}.json")))
{
var myJsonResponse = File.ReadAllText(path);
var jObject = JsonConvert.DeserializeObject(myJsonResponse) as JObject;
var jToken = jObject?.SelectToken("AppSettings.NativeAppPath");
jToken?.Replace(newPath);
var updatedJson = jObject?.ToString();
File.WriteAllText(path, updatedJson);
}
}
This works when I run the application from the source files but I would like to publish and share this application with my colleagues however I assume that the published application does not have direct access to the directories that I am referencing or something like that.
Pretty much I want to know if there is a way for me to be able to get this logic working with a published version of my application. I tried including the "AppSettingsFiles" folder into the published directory but the app still appeared to be referencing the files from its own metadata maybe... I'm not sure, hopefully someone can help me, please let me know if you need more information?
I need to get the directory name from its path regardless of any of having a trailing backslash. For example, user may input one of the following 2 strings and I need the name of logs directory:
"C:\Program Files (x86)\My Program\Logs"
"C:\Program Files (x86)\My Program\Logs\"
None of the following gives correct answer ("Logs"):
Path.GetDirectoryName(m_logsDir);
FileInfo(m_logsDir).Directory.Name;
They apparently analyze the path string and in the 1st example decide that Logs is a file while it's really a directory.
So it should check if the last word (Logs in our case) is really a directory; if yes, return it, if no (Logs might be a file too), return a parent directory. If would require dealing with the actual filesystem rather than analyzing the string itself.
Is there any standard function to do that?
new DirectoryInfo(m_logsDir).Name;
This may help
var result = System.IO.Directory.Exists(m_logsDir) ?
m_logsDir:
System.IO.Path.GetDirectoryName(m_logsDir);
For this we have a snippet of code along the lines of:
m_logsDir.HasFlag(FileAttribute.Directory); //.NET 4.0
or
(File.GetAttributes(m_logsDir) & FileAttributes.Directory) == FileAttributes.Directory; // Before .NET 4.0
Let me rephrase my answer, because you have two potential flaws by the distinguishing factors. If you do:
var additional = #"C:\Program Files (x86)\My Program\Logs\";
var path = Path.GetDirectoryName(additional);
Your output would be as intended, Logs. However, if you do:
var additional = #"C:\Program Files (x86)\My Program\Logs";
var path = Path.GetDirectoryName(additional);
Your output would be My Program, which causes a difference in output. I would either try to enforce the ending \ otherwise you may be able to do something such as this:
var additional = #"C:\Program Files (x86)\My Program\Logs";
var filter = additional.Split('\\');
var getLast = filter.Last(i => !string.IsNullOrEmpty(i));
Hopefully this helps.
Along the lines of the previous answer, you could enforce the trailing slash like this:
Path.GetDirectoryName(m_logsDir + "\");
Ugly but it seems to work - whether there's 0 or 1 slash at the end. The double-slash is treated like a single-slash by GetDirectoryName.
I'm using C# to get the exact path of the specific folder in windows system by giving the folder name. Is their any way to get the folder path by giving the folder name, where the folder name will be unique.
Update:
Folder is created at run time with current time as the name. This
process is done by the application. Here i know the folder name but i
didn't know path, because path is selected by the user during
installation and installation is done before very long time.
That changes the question considerably. Why not use the application to tell you where it lives:
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.startuppath.aspx
I had a similar idea ages ago and wrote about it as a Code Project Tip:
http://www.codeproject.com/Tips/132804/Open-folders-using-a-Run-Command
Otherwise you would need to index every folder on the PC and make them unique names and look up the full path that way.
The other suggestion I have is using LogParser as the Most efficient way to find all exe files on disk using C#? Its a free Microsoft product but I'm not sure about re-dist permissions, I had to include it in my package separately last time I used it. It full on flys, faster than a speeding train!
I found a Log Parser example that finds folders, you could try it out and adapt it if its useful:
SELECT TOP 1 * FROM C:\TFS\Project\*.* WHERE INDEX_OF(Path, 'Database') > 0
The good folks over at http://visuallogparser.codeplex.com/ have
provided us with the source code.
Open the VisualLogParser solution in VS2010, ignore the prompt about debugging, after the solution loads, F5, set the combo-box to FS (FileSystem), paste in this query and press go.
You could probably use something like this, but it'll be rather slow, depending on how many folders needed to be looked through.
Use it like FindFullPath(rootFolder, folderNameToLookFor)
public static string FindFullPath(string path, string folderName)
{
if (string.IsNullOrWhiteSpace(folderName) || !Directory.Exists(path))
{
return null;
}
var di = new DirectoryInfo(path);
return findFullPath(di, folderName);
}
private static string findFullPath(DirectoryInfo directoryInfo, string folderName)
{
if (folderName.Equals(directoryInfo.Name, StringComparison.InvariantCultureIgnoreCase))
{
return directoryInfo.FullName;
}
try
{
var subDirs = directoryInfo.GetDirectories();
return subDirs.Select(subDir => findFullPath(subDir, folderName)).FirstOrDefault(fullPath => fullPath != null);
}
catch
{
// DirectoryNotFound, Security, UnauthorizedAccess
return null;
}
}
See following link
string dirName = new DirectoryInfo(#"c:\projects\roott\wsdlproj\devlop\beta2\text").Name;
I'm about to develop a software in C# that must select random folders (in a scenario with 10.000 folders more or less) that follow these rules:
select only the ones which contains files;
the software must stop the selection when the size of selected folder is 8GB;
when I copy a single folder, I need to keep the whole path of that folder (if c:\folder\temp\hello is the copied one, I want to keep d:\COPIED\folder\temp\hello);
I think I will do somethings like:
analyze the whole list of folder starting from an assigned root;
select random "line" in this list, moving it to the "selected list", counting the size;
when I reach 8GB, I stop this first phase, and I start to copy it;
I think here it is not a big trouble. What do you think about? Any suggestions?
My real problem will to "recreate" the whole path for each single folder when I move it.
How can I do it? Create folder for each level with C# API or is there a workaround?
So the last paragraph is the question? I understand it in the following way:
How to create a new path that contains the same path as the source but
with a different root?
Then you can use the Path class and it's static methods + String.Substring to get the new path.
D:\Copied is your root destination folder which you use in Path.Combine. Then you have to add the old-path without it's root-folder(there is no method in Path for this, i'll use Substring):
var rootDest = #"D:\Copy"; // your root directory
var pathSource = #"C:\Test\Test.txt"; // a sample file
var root = Path.GetPathRoot(pathSource); // C:\
var oldPathWithoutRoot = pathSource.Substring(root.Length); // Test\Test.txt
var newPath = Path.Combine(rootDest, oldPathWithoutRoot); // D:\Copy\Test\Test.txt
Then use File.Copy to copy all files in the folder from the old to the new path.
You have to check if the directory exists and create it otherwise:
var targetDir = Path.GetDirectoryName(newPath);
if (!Directory.Exists(targetDir))
{
Directory.CreateDirectory(targetDir); // D:\Copy\Test
}
File.Copy(pathSource, newPath);
I am trying to write out a text file to: C:\Test folder\output\, but without putting C:\ in.
i.e.
This is what I have at the moment, which currently works, but has the C:\ in the beginning.
StreamWriter sw = new StreamWriter(#"C:\Test folder\output\test.txt");
I really want to write the file to the output folder, but with out having to have C:\ in the front.
I have tried the following, but my program just hangs (doesn't write the file out):
(#"\\Test folder\output\test.txt");
(#".\Test folder\output\test.txt");
("//Test folder//output//test.txt");
("./Test folder//output//test.txt");
Is there anyway I could do this?
Thanks.
Thanks for helping guys.
A colleague of mine chipped in and helped as well, but #Kami helped a lot too.
It is now working when I have:
string path = string.Concat(Environment.CurrentDirectory, #"\Output\test.txt");
As he said: "The CurrentDirectory is where the program is run from.
I understand that you would want to write data to a specified folder. The first method is to specify the folder in code or through configuration.
If you need to write to specific drive or current drive you can do the following
string driveLetter = Path.GetPathRoot(Environment.CurrentDirectory);
string path = diveLetter + #"Test folder\output\test.txt";
StreamWriter sw = new StreamWriter(path);
If the directory needs to be relative to the current application directory, then user AppDomain.CurrentDomain.BaseDirectory to get the current directory and use ../ combination to navigate to the required folder.
You can use System.IO.Path.GetDirectoryName to get the directory of your running application and then you can add to this the rest of the path..
I don't get clearly what you want from this question , hope this get it..
A common technique is to make the directory relative to your exe's runtime directory, e.g., a sub-directory, like this:
string exeRuntimeDirectory =
System.IO.Path.GetDirectoryName(
System.Reflection.Assembly.GetExecutingAssembly().Location);
string subDirectory =
System.IO.Path.Combine(exeRuntimeDirectory, "Output");
if (!System.IO.Directory.Exists(subDirectory))
{
// Output directory does not exist, so create it.
System.IO.Directory.CreateDirectory(subDirectory);
}
This means wherever the exe is installed to, it will create an "Output" sub-directory, which it can then write files to.
It also has the advantage of keeping the exe and its output files together in one location, and not scattered all over the place.