.NET Settings Relative Path - visual-studio

I am working on an application where I have an images folder relative to my application root. I want to be able to specify this relative path in the Properties -> Settings designer eg. "\Images\". The issue I am running into is in cases where the Environment.CurrentDirectory gets changed via an OpenFileDialog the relative path doesn't resolve to the right location. Is there a way to specifiy in the Settings file a path that will imply to always start from the application directory as opposed to the current directory? I know I can always dynamically concatenate the application path to the front of the relative path, but I would like my Settings property to be able to resolve itself.

As far as I know, there is no built-in functionality that will allow this type of path resolution. Your best option is to dynamically determine the applications executing directory and concatenate to it your images path. You don't want to use Environment.CurrentDirectory specifically for the reasons you mention - the current directory may not always be correct for this situation.
The safest code I've found to find the executing assembly location is this:
public string ExecutingAssemblyPath()
{
Assembly actualAssembly = Assembly.GetEntryAssembly();
if (this.actualAssembly == null)
{
actualAssembly = Assembly.GetCallingAssembly();
}
return actualAssembly.Location;
}

Are you looking for Application.ExecutablePath ? That should tell you where the application's executable is, remove the executable name, and then append your path to it.

2 options:
The code that uses the setting can resolve the setting against the directory of the current executing assembly.
You can create your own type that serializes as a string relative to the executing assembly, and has an accessor for the full path that will resolve against the directory of the current executing assembly.
Code sample:
string absolutePath = Settings.Default.ImagePath;
if(!Path.IsPathRooted(absolutePath))
{
string root = Assembly.GetEntryAssembly().Location;
root = Path.GetDirectoryName(root);
absolutePath = Path.Combine(root, absolutePath);
}
The nice thing about this code is that it allows a fully qualified path, or a relative path, in your settings. If you need the path to be relative to a different assembly, you can change which assembly's location you use - GetExecutingAssembly() will give you the location of the assembly with the code you're running, and GetCallingAssembly() would be good if you go with option 2.

This seem to work in both WinForms and ASP.NET (gives the path to the config file):
new System.IO.FileInfo(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile).Directory;
For Windows and Console applications, the obvious way is by using:
Application.StartupPath

I suggest you to use Assembly.CodeBase, as shown below:
public static string RealAssemblyFilePath()
{
string dllPath=Assembly.GetExecutingAssembly().CodeBase.Substring(8);
return dllPath;
}
You can try Application.ExecutablePath. But you need to make reference to System.Windows.Forms. This may not be a good idea if you want your class library to steer clear of forms and UI stuff.
You can try the Assembly.GetExecutingAssembly().Location. But if, somehow, you do a "Shadow Copy" before you run your application (like the default NUnit behavior), then this property will return you the shadow copy location, not the real, physical location.
The best way is to implement a function that calls the CodeBase property of Assembly object and chop off the irrelevant portion of the string.

I use the following two methods to help with that:
public static IEnumerable<DirectoryInfo> ParentDirs(this DirectoryInfo dir) {
while (dir != null) {
yield return dir;
dir = dir.Parent;
}
}
public static DirectoryInfo FindDataDir(string relpath, Assembly assembly) {
return new FileInfo((assembly).Location)
.Directory.ParentDirs()
.Select(dir => Path.Combine(dir.FullName + #"\", relpath))
.Where(Directory.Exists)
.Select(path => new DirectoryInfo(path))
.FirstOrDefault();
}
The reason to look at parent dirs to to be easier in use during development when various build scripts end up sticking things in directories like bin\x64\Release\NonsensePath\.

Related

Access the Android Special Folder Path by using Environment

I want to save my logs to a folder which I can access with windows explorer. For example I want to create my log in the following path
This PC\Galaxy A5 (2017)\Phone\Android\data\MyApp\files
So I tried to use Environment variables... I get such as
/data/user/...
But here i cannot see the file what I created (using code I can access the path but I want to see in the explorer).
how I can create a path like above with code?
When I tried this code
var finalPath2 = Android.OS.Environment.GetExternalStoragePublicDirectory
(Android.OS.Environment.DataDirectory.AbsolutePath);
I get the path "/storage/emulated/0/data"
and
If i use the code
var logDirectory =Path.Combine(System.Environment.GetFolderPath
(System.Environment.SpecialFolder.ApplicationData),"logs");
I get the following path like:
/data/user/0/MyApp/files/.config/logs
and
var logDirectory =Path.Combine(System.Environment.GetFolderPath
(System.Environment.SpecialFolder.MyDocuments),"logs");
"/data/user/0/IM.OneApp.Presentation.Android/files/logs"
but unfortunately I cannot access this folder by explorer....
This PC\Galaxy A5 (2017)\Phone\Android\data\MyApp\files
So how to find out this path in c# by using environments?
Update:
when I give the following path hardcoded, it creates the file where I want..
logDirectory = "/storage/emulated/0/Android/data/MyApp/files/logs";
is there any environment to create this path? I can combine 2 environments and do some string processing in order to create this path. But maybe there is an easier way?
You are looking for the root of GetExternalFilesDir, just pass a null:
Example:
var externalAppPathNoSec = GetExternalFilesDir(string.Empty).Path;
Note: This is a Context-based instance method, you can access it via the Android application context, an Activity, etc... (see the link below to the Android Context docs)
Shared storage may not always be available, since removable media can be ejected by the user. Media state can be checked using Environment.getExternalStorageState(File).
There is no security enforced with these files. For example, any application holding Manifest.permission.WRITE_EXTERNAL_STORAGE can write to these files.
re: https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)
string docFolder = Path.Combine(System.Environment.GetFolderPath
(System.Environment.SpecialFolder.MyDocuments), "logs");
string libFolder = Path.Combine(docFolder, "/storage/emulated/0/Android/data/MyApp/files/logs");
if (!Directory.Exists(libFolder))
{
Directory.CreateDirectory(libFolder);
}
string destinationDatabasePath = Path.Combine(libFolder, "temp.db3");
db.Backup( destinationDatabasePath, "main");

Getting the filename/path from MvvmCross Plugins.DownloadCache

I'm currently using MvvmCross DownloadCache -- and it's working alright -- especially nice when I just need to drop in an Image URL and it automagically downloads / caches the image and serves up a UIImage.
I was hoping to leverage the code for one other use case -- which is I'd like to grab source images from URL's and cache the files on the local file system, but what I really want for this other use case is the image path on the local file system instead of the UIImage itself.
What would help me most if I could get an example of how I might accomplish that. Is it possible to make that happen in a PCL, or does it need to go into the platform specific code?
Thanks -- that works, but just in case anyone else is following along, I wanted to document how I got the Mvx.Resolve<IMvxFileDownloadCache>() to work. In my setup.cs (in the touch project), I had:
protected override void InitializeLastChance ()
{
Cirrious.MvvmCross.Plugins.DownloadCache.PluginLoader.Instance.EnsureLoaded();
Cirrious.MvvmCross.Plugins.File.PluginLoader.Instance.EnsureLoaded();
Cirrious.MvvmCross.Plugins.Json.PluginLoader.Instance.EnsureLoaded();
...
}
But that wasn't enough, because nothing actually registers IMvxFileDownloadCache inside the DownloadCache plugin (which I was expecting, but it's just not the case).
So then I tried adding this line here:
Mvx.LazyConstructAndRegisterSingleton<IMvxFileDownloadCache, MvxFileDownloadCache>();
But that failed because MvxFileDownloadCache constructor takes a few arguments. So I ended up with this:
protected override void InitializeLastChance ()
{
...
var configuration = MvxDownloadCacheConfiguration.Default;
var fileDownloadCache = new MvxFileDownloadCache(
configuration.CacheName,
configuration.CacheFolderPath,
configuration.MaxFiles,
configuration.MaxFileAge);
Mvx.RegisterSingleton<IMvxFileDownloadCache>(fileDownloadCache);
...
}
And the resolve works okay now.
Question:
I do wonder what happens if two MvxFileDownloadCache objects that are configured in exactly the same way will cause issues by stepping on each other. I could avoid that question by changing the cache name on the one I'm constructing by hand, but I do want it to be a single cache (the assets will be the same).
If you look at the source for the plugin, you'll find https://github.com/MvvmCross/MvvmCross/blob/3.2/Plugins/Cirrious/DownloadCache/Cirrious.MvvmCross.Plugins.DownloadCache/IMvxFileDownloadCache.cs - that will give you a local file path for a cached file:
public interface IMvxFileDownloadCache
{
void RequestLocalFilePath(string httpSource, Action<string> success, Action<Exception> error);
}
You can get hold of a service implementing this interface using Mvx.Resolve<IMvxFileDownloadCache>()
To then convert that into a system-wide file path, try NativePath in https://github.com/MvvmCross/MvvmCross/blob/3.2/Plugins/Cirrious/File/Cirrious.MvvmCross.Plugins.File/IMvxFileStore.cs#L27

Xtext get the absolute path of the generated files

I want to access the file generated by Xtext to compile it automatically. So I need its absolute path. It's enough to get the absolute path of the current project at run-time. Any idea how I can get it?
I am working inside the "MyDslGenerator" Class. I tried to get it from the "resource" in
override void doGenerate(Resource resource, IFileSystemAccess fsa)
but couldn't find it.
Help is highly appreciated.
I ended up using this code:
var uri = (fsa as IFileSystemAccessExtension2).getURI(fileName)
maybe you can use the Interface org.eclipse.xtext.generator.IFileSystemAccessExtension2. the passed IFileSystemAccess may implement this interface too.

How to create the path to desktop for the target user..in C#.net

I am developing image extraction application in .net using C# in VS2010.
i have created a path ,where the image will be extracted.But this path is specific to my system.
string image1 = "c:\\Users\\Raghu\\Desktop\\r.bmp";
I want a path which should be general i.e when the project will be deployed ,the output file should be extracted in Target Users desktop.
how create a folder on desktop and and all my extracted files goes in it.
Any ideas! please help me!!
Next code will return path to the desktop of current user:
Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
So, in your case it would be
string desktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
string image1 = System.IO.Path.Combine(desktop, "r.bmp");
Environment.SpecialFolder (http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx) contains many definitions of system folder paths. Take a look which you need.
You would use the DesktopDirectory for Environment.SpecialFolder. Something like this:
public static string GetDesktopDirectory()
{
return Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
}
Then using the result of that method, you can use Path.Combine to append a file name to it.
var myFilePath = Path.Combine(GetDesktopDirectory(), "r.bmp");
Path.Combine is the general solution for this, as directly concating strings may result in double slashes, etc. This takes care of that for you.

Getting the macro value of project's TargetPath via DTE

I need to get the absolute output path of the project's assembly via DTE. I tried doing this using this method, where I would access the OutputPath property, combining it with the assembly name, however this produces the relative path, such as:
..\..\Output\AnyCPU\Debug\MyAssembly.dll
Using Path.GetFullPath is not good for me, because my project might be executing from another location.
I noticed that the $(TargetPath) macro (in Build Events tab in project properties) contains the full path of the assembly. How can I access this value programmatically from the DTE?
Actual question is - how do I get the absolute output path of the project?
I don't know how to programmatically access the "$(TargetPath)", I agree that that could've been the best solution.
However, the approach you mentioned should still be workable,since the OutputPath property is relative to the folder in which the project file resides. (Please let me know if I'm missing some scenario where this is not the case?)
So you can do something similar to this:
private static string GetProjectExecutable(Project startupProject, Configuration config)
{
string projectFolder = Path.GetDirectoryName(startupProject.FileName);
string outputPath = (string)config.Properties.Item("OutputPath").Value;
string assemblyFileName = (string)startupProject.Properties.Item("AssemblyName").Value + ".exe";
return Path.Combine(new[] {
projectFolder,
outputPath,
assemblyFileName
});
}
(the overload of Path.Combine used here is only available in .NET 4.0 but you could always backport it)

Resources