I have an app in which the user needs to access certain files in a user set and selected folder.
The folder and files paths need to be easily accessed (short simple path).
I use the Properties Settings to hold the Folder and File paths, but for some reason each time I re-start the program the Folder and File paths are lost.
I have followed and checked the program and all seems to be OK (except something I am missing, apparently).
I attach here the program snippet in two parts: The search for path and the setting in case path / file not found. (removed exception handling to save on lines)
public Main() //part of Main, stripped off exception handling)
{
//..........
dataFolder = Properties.Settings.Default.dataFolder;
if (!Directory.Exists(dataFolder))
{
SetDataFolder();
}
configFile = Properties.Settings.Default.configFile;
if (!File.Exists(configFile))
{
SetConfigFile();
}
dataFile = Properties.Settings.Default.dataFile;
if (!File.Exists(dataFile))
{
SetDataFile();
}
loadParamsFromFile(configFile); //Load the previously saved controls.
public String SetDataFolder()
{
FolderBrowserDialog dialog = new FolderBrowserDialog();
DialogResult folder = dialog.ShowDialog();
if (folder == DialogResult.OK)
{
dataFolder = dialog.SelectedPath;
Directory.CreateDirectory(dataFolder);
dataFolder = Path.GetFullPath(dataFolder);
Properties.Settings.Default.dataFolder = dataFolder;
Properties.Settings.Default.Save();
return dataFolder;
}
else return null;
}
private string SetDataFile()
{
dataFile = $"{dataFolder}\\{textBoxSampleID.Text.Replace("/r", "").Trim()}.txt";
File.Create(dataFile).Close();
Properties.Settings.Default.dataFile = dataFile;
Properties.Settings.Default.Save();
return dataFile;
}
private string SetConfigFile()
{
configFile = $"{dataFolder}\\electroplating.cfg";
File.Create(configFile).Close();
Properties.Settings.Default.configFile = configFile;
Properties.Settings.Default.Save();
return configFile;
}
Check out this question:
How to change application settings (Settings) while app is open?
I would suggest using Path.Combine() for the construction of the file paths.
If it still doesn't work, you could also try using the registry for storing the values.
string dataFilePath = Path.Combine(dataFolder, textBoxSampleID.Text.Replace("/r", "").Trim());
RegistryKey key = Registry.LocalMachine.CreateSubKey(#"SOFTWARE\Company");
if (key != null)
{
key.SetValue("dataFilePath", dataFilePath);
}
You could then use string dataFilePath = (string)key.GetValue("dataFilePath") to get the value out of the registry.
Related
I'm trying to build a simple archiving program. We have files scattered throughout the system so part of the routine checks to see if a shortcut was put into the system and if so, to fetch all of the files from where the shortcut points to. It was all working fine a few weeks ago, but when I applied some visual studio updates it seems to have ceased working.
var downloadFilePath = Path.Combine(storFolder, caseEntity.ID, caseDocs.FileName);
if (downloadFilePath.Contains(".lnk"))
{
try
{
Console.WriteLine("Link Found. Now Processing.");
DirectoryInfo source = new DirectoryInfo(GetShortcutTargetFile(downloadFilePath));
DirectoryInfo target = new DirectoryInfo(storFolder + "\\" + nuFolder);
CopyFilesRecursively(source, target);
}
catch { Console.WriteLine("Bad link, no documents found."); }
}
Using break points it looks like the problem is in the "DirectoryInfo source..." line but I can't figure out why it's failing.
This is the GetShortcutTargetFile function.
public static string GetShortcutTargetFile(string shortcutFilename)
{
string pathOnly = Path.GetDirectoryName(shortcutFilename);
string filenameOnly = Path.GetFileName(shortcutFilename);
Shell shell = new Shell();
Folder folder = shell.NameSpace(pathOnly);
FolderItem folderItem = folder.ParseName(filenameOnly);
if (folderItem != null)
{
ShellLinkObject link = (ShellLinkObject)folderItem.GetLink;
return link.Path;
}
return string.Empty; // not found
}
I have a Winforms application that is supposed to create a subdirectory in the Public Documents folder if the directory does not exist and save a text file to it. However, if the subdirectory does not exist, it actually creates another directory called Public Documents under "C:/Users/Public" rather than just creating a subdirectory under the existing "C:/Users/Public" folder. (In the example below the subdirectory is the variable 'token'.) So I end up with 2 folders called Public Documents:
Here is my code:
if (result == DialogResult.Yes)
{
subPath = #"C:\Users\Public\Public Documents\" + token + #"\Tests\";
}
else if (result == DialogResult.No)
{
subPath = #"C:\Users\Public\Public Documents" + #"\Tests\";
}
TestModel testCall = new TestModel
{
Name = frm.fileName,
MethodName = txtApiMethod.Text,
Parameter = rtxtJson.Text,
SchemaKey = txtSchemaKey.Text
};
bool exists = System.IO.Directory.Exists(subPath);
string fileName = frm.fileName + ".txt";
string json = JsonConvert.SerializeObject(testCall);
string filePath = subPath + fileName;
if (!exists)
{
System.IO.Directory.CreateDirectory(subPath);
}
using (StreamWriter file = File.CreateText(filePath))
{
file.Write(json);
}
Can someone tell me why it is creating a duplicate named directory, and what I can do to have just create a new subdirectory under the existing directory?
Any assistance is greatly appreciated!
C:\Users\Public\Public Documents is a display name. I have a french Windows, and the display name is C:\Users\Public\Documents publics
The real path is C:\Users\Public\Documents
Display :
Real :
To make sure you are using the correct folder path (for some reasons, d: could be used instead, or the path could be totaly different. Never use hardcoded path), you can use System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonDocuments); that links to C:\Users\Public\Documents, such as :
var PublicDocuments = System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonDocuments);
if (result == DialogResult.Yes)
{
subPath = PublicDocuments + #"\"+ token + #"\Tests\";
}
else if (result == DialogResult.No)
{
subPath = PublicDocuments + #"\Tests\";
}
See the documentation for more infos about System.Environment.SpecialFolder and System.Environment.GetFolderPath()
I create a FolderBrowserDialog as follows (only an excerpt -not complete code):
string tempSetWorkingPath = null;
try
{
FolderBrowserDialog folderDlg = new System.Windows.Forms.FolderBrowserDialog();
folderDlg.ShowNewFolderButton = true;
folderDlg.Description = "Selected your working folder. This is where your PDF files will be saved.";
folderDlg.RootFolder = Environment.SpecialFolder.MyComputer;
folderDlg.SelectedPath = (Convert.ToString(WorkingPath).Trim().Length == 0) ? ((int)Environment.SpecialFolder.MyComputer).ToString() : WorkingPath;
if (folderDlg.ShowDialog() == DialogResult.OK)
{
tempSetWorkingPath = folderDlg.SelectedPath;
}
else
{
tempSetWorkingPath = "";
}
}
...
The code works well, except the only folders that are showing are the local folders. Users have DropBox and OneDrive shared folders on their systems and to select one of those directories, the user needs to cycle through the windows user directories and select the folder from there. On some systems I have seen over the last few months, I've seen the DropBox and OneDrive directories appear below the DeskTop directory ... but I have not, despite hours of searching - found a way to achive that.
How can I achieve that?
MTIA
DWE
Given I have observed a large number of queries posted here and elsewhere regarding the inclusion of the directories, including shared directories and given the response by # Mailosz, it seems that the root folder property of the folder dialog holds the key - it Gets or sets the root folder where the browsing starts from and thats what my code was missing.
The full code to the function referred to in my question appears below, in the event it assists someone else.
/// <summary>
/// presents the user with a folder dialog
/// Returns a full qualified directory chosen by the user
/// </summary>
/// <param name="WorkingPath">if a fully qualified directory name is provided, then the folder structure in the folder dialog will open to the directory selected</param>
/// <returns>Returns a full qualified directory chosen by the user or if no directory was chosen, an empty string</returns>
public string SetWorkingPath(string WorkingPath)
{
string tempSetWorkingPath = null;
try
{
FolderBrowserDialog folderDlg = new System.Windows.Forms.FolderBrowserDialog();
// check our proposed working path and if its valid
if((!string.IsNullOrEmpty(WorkingPath) && (WorkingPath != null)))
{
if (!Directory.Exists(WorkingPath))
WorkingPath = string.Empty;
}
else // if we are empty or null set us to empty
{
WorkingPath = string.Empty;
}
folderDlg.ShowNewFolderButton = true;
folderDlg.Description = "Please select your working folder. This is where your PDF files will be saved.";
folderDlg.RootFolder = Environment.SpecialFolder.Desktop;//.MyComputer;
folderDlg.SelectedPath = (Convert.ToString(WorkingPath).Trim().Length == 0) ? ((int)Environment.SpecialFolder.MyComputer).ToString() : WorkingPath;
if (folderDlg.ShowDialog() == DialogResult.OK)
{
// make sure we have a backslash on the end of our directory string
tempSetWorkingPath = PathAddBackslash(folderDlg.SelectedPath);
}
else
{
// return an empty string
tempSetWorkingPath = string.Empty;
}
}
catch (Exception ex)
{
tempSetWorkingPath = string.Empty;
throw (ex);
}
return tempSetWorkingPath;
}
public string PathAddBackslash(string path)
{
// They're always one character but EndsWith is shorter than
// array style access to last path character. Change this
// if performance are a (measured) issue.
string separator1 = Path.DirectorySeparatorChar.ToString();
string separator2 = Path.AltDirectorySeparatorChar.ToString();
// Trailing white spaces are always ignored but folders may have
// leading spaces. It's unusual but it may happen. If it's an issue
// then just replace TrimEnd() with Trim(). Tnx Paul Groke to point this out.
path = path.TrimEnd();
// Argument is always a directory name then if there is one
// of allowed separators then I have nothing to do.
if (path.EndsWith(separator1) || path.EndsWith(separator2))
return path;
// If there is the "alt" separator then I add a trailing one.
// Note that URI format (file://drive:\path\filename.ext) is
// not supported in most .NET I/O functions then we don't support it
// here too. If you have to then simply revert this check:
// if (path.Contains(separator1))
// return path + separator1;
//
// return path + separator2;
if (path.Contains(separator2))
return path + separator2;
// If there is not an "alt" separator I add a "normal" one.
// It means path may be with normal one or it has not any separator
// (for example if it's just a directory name). In this case I
// default to normal as users expect.
return path + separator1;
}
System.IO.CreateDirectory() is not available on .NET for Windows Store Apps.
How can I implement this equivalent method? StorageFolder.CreateFolderAsync() creates a subfolder inside the current folder, but in my case I have a path like and need to create all folders that doesn't exist in this path.
The path is inside the app's sandbox in windows.
There's no API with exactly the same behaviour of System.IO.CreateDirectory(), so I implemented it using Windows.Storage classes:
// Any and all directories specified in path are created, unless they already exist or unless
// some part of path is invalid. If the directory already exists, this method does not create a
// new directory.
// The path parameter specifies a directory path, not a file path, and it must in
// the ApplicationData domain.
// Trailing spaces are removed from the end of the path parameter before creating the directory.
public static void CreateDirectory(string path)
{
path = path.Replace('/', '\\').TrimEnd('\\');
StorageFolder folder = null;
foreach(var f in new StorageFolder[] {
ApplicationData.Current.LocalFolder,
ApplicationData.Current.RoamingFolder,
ApplicationData.Current.TemporaryFolder } )
{
string p = ParsePath(path, f);
if (f != null)
{
path = p;
folder = f;
break;
}
}
if(path == null)
throw new NotSupportedException("This method implementation doesn't support " +
"parameters outside paths accessible by ApplicationData.");
string[] folderNames = path.Split('\\');
for (int i = 0; i < folderNames.Length; i++)
{
var task = folder.CreateFolderAsync(folderNames[i], CreationCollisionOption.OpenIfExists).AsTask();
task.Wait();
if (task.Exception != null)
throw task.Exception;
folder = task.Result;
}
}
private static string ParsePath(string path, StorageFolder folder)
{
if (path.Contains(folder.Path))
{
path = path.Substring(path.LastIndexOf(folder.Path) + folder.Path.Length + 1);
return path;
}
return null;
}
To create folders outside your app's sandbox in windows store app, you'll have to add the document library in app-manifest, along with file permissions.
For a much more detailed explanation regarding library and documents, Refer this blog
I am trying to do following with c#.
1) Open Firefox Browser-->Tools-->Options-->General Tab--->Downloads--->Always ask me where to save file.
I want to do this whole process in my application with c#. I want that when download window opens, the radio button in "Always ask me where to save file" option gets checked automatically.
I have tried from various links, but all is in vain.
Here is the full code, console application.
Summary: preferences file is located in application roaming folder, something like this on windows 7:
C:\Users\MYNAME\AppData\Roaming\Mozilla\Firefox\Profiles\d9i9jniz.default\prefs.js
We alter this file so that it includes "user_pref("browser.download.useDownloadDir", false);"
Restart firefox, and done. Only run this application when firefox is not running.
static void Main(string[] args)
{
if (isFireFoxOpen())
{
Console.WriteLine("Firefox is open, close it");
}
else
{
string pathOfPrefsFile = GetPathOfPrefsFile();
updateSettingsFile(pathOfPrefsFile);
Console.WriteLine("Done");
}
Console.ReadLine();
}
private static void updateSettingsFile(string pathOfPrefsFile)
{
string[] contentsOfFile = File.ReadAllLines(pathOfPrefsFile);
// We are looking for "user_pref("browser.download.useDownloadDir", true);"
// This needs to be set to:
// "user_pref("browser.download.useDownloadDir", false);"
List<String> outputLines = new List<string>();
foreach (string line in contentsOfFile)
{
if (line.StartsWith("user_pref(\"browser.download.useDownloadDir\""))
{
Console.WriteLine("Found it already in file, replacing");
}
else
{
outputLines.Add(line);
}
}
// Finally add the value we want to the end
outputLines.Add("user_pref(\"browser.download.useDownloadDir\", false);");
// Rename the old file preferences for safety...
File.Move(pathOfPrefsFile, Path.GetDirectoryName(pathOfPrefsFile) + #"\" + Path.GetFileName(pathOfPrefsFile) + ".OLD." + Guid.NewGuid().ToString());
// Write the new file.
File.WriteAllLines(pathOfPrefsFile, outputLines.ToArray());
}
private static string GetPathOfPrefsFile()
{
// Get roaming folder, and get the profiles.ini
string iniFilePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Mozilla\Firefox\profiles.ini";
// Profiles.ini tells us what folder the preferences file is in.
string contentsOfIni = File.ReadAllText(iniFilePath);
int locOfPath = contentsOfIni.IndexOf("Path=Profiles");
int endOfPath = contentsOfIni.IndexOf(".default", locOfPath);
int startOfPath = locOfPath + "Path=Profiles".Length + 1;
int countofCopy = ((endOfPath + ".default".Length) - startOfPath);
string path = contentsOfIni.Substring(startOfPath, countofCopy);
string toReturn = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + #"\Mozilla\Firefox\Profiles\" + path + #"\prefs.js";
return toReturn;
}
public static bool isFireFoxOpen()
{
foreach (Process proc in Process.GetProcesses())
{
if (proc.ProcessName == "firefox")
{
return true;
}
}
return false;
}
What have you tried?
Firefox settings are stored in your profile, so I'd guess you can change the contents of the given file. Type about:config to find the setting you're looking for, I guess it's in the browser.download tree, alter it (after you made sure the browser isn't running) and you should be good to go.