C# - Relative path of class - c#

Trying to get relative path of config file, which is next to a class in core project, and also trying to avoid hardcoded relative paths (i.e. "../../../seleniumconfig.json")
This is my project structure,
Awesome.Core (library project)
Selenium (folder)
ZSelenium.cs
seleniumconfig.json (want it here so only powerusers can reach to this file)
Awesome.OtherProject1 (calling project, references Awesome.Core)
Program.cs
Awesome.OtherProject2 (another calling project, references Awesome.Core)
Program.cs
Program.cs (in Awesome.OtherProject1)
using (var scope = Container.BeginLifetimeScope())
{
var selenium = scope.Resolve<ZSelenium>();
...
}
ZSelenium.cs
var rootDir = new DirectoryInfo(Environment.CurrentDirectory);
// "/users/myuser/Documents/MyProject/AwesomeProject.OtherProject"
I can construct my relative path from rootDir variable, but there will be a lot of hardcoded ../../.. stuff which I would like to avoid. Also, if I call ZSelenium.cs from another project, the relative path might change.
Does anyone know a better way to get the path of ZSelenium.cs within the core project?

Configurations files do not belong into the Programm folder, ever. We did kind of do it anyway in the Windows 98 times, but it was frowned upon back then. Since XP is it not reliably possible anymore to write such a configuration file. The Programm folders is protected. Most users can only read them, not write them for security reasons. And that includes any programms started by that user too.
If you want to store user or system specific settings, that is what the special folders are there for. Their one defining purpose is that whatever user runs your programm, should have read (and likely write) access to his own and all shared folders.
You may be able to add a "default configuration" to the Programm directory to use as pattern for new users. But even for that there is a existing structure (the default user folder) so you can leave placing the template to the Setup.

Related

Where to store uploaded files?

I have an Asp.net web service and I need to store user-uploaded files. At first I thought of storing them in the App_Data folder, however, I now see that when publishing from Visual Studio with the 'Remove additional files at destination' option, it will remove files from the App_Data folder despite checking also the 'Exclude files from the App_Data folder'.
(There seem to be workarounds for this, but if it's not through the 'Publish' designer, I'm afraid that at some point the files will be removed, either due to human error, or some future MS update that will break it.)
So, I need some folder that is not under the publish path, and yet accessible (to the web app, not to the public), and that will not be auto-deleted.
EDIT
This is being done on a web hosted environment, so privileges are limited.
You may choose any folder in any path (even in another drive) as long as your asp.net application has privilege to write to it. you may even create a virtual directory for this purpose.
Edit
As you are using a hosting environment, I don't know which options they have provided, as sometimes they restrict a lot, however in most cases when you are creating a new website in your hosting environment, you are asked to provide the path something like : \wwwroot you may want to change it to something like:
\somepath\wwwroot (of course you should create somepath first), and you will have access to somepath too.

Reading files from a folder in a class library

I'm having a brain fart at the moment. I have a set of files that are read in by a class library in a .NET Web Site. The issue is the files are used in three different sites (all the sites reference the class library), so I don't want to copy the files across all three. What I want to do is have a folder in the class library itself as a shared resource, something like this:
ClassLib
\Templates
-file1.xml
-file2.pdf
-MyClass.cs
and have MyClass read the files from the Templates directory. Easy enough, except that MyClass.cs is called from a page, let's call it Default.aspx. Now MyClass.cs has code like the following:
IList<string> files = GetTemplateFiles(); // returns the path to the template files e.g. Templates/file1.xml
foreach (string file in files) {
if (File.Exists(file)) {
// do things here...
}
}
File.Exists is always false, seemingly because it is looking in the default directory and not the path to ClassLib (which is something like C:\Projects\Shared\MyLib\). Now, I cannot use AppDomain.CurrentDomain.BaseDirectory because this varies based on the web site which is calling it; the templates should always be available from the Templates directory in the class library, not the calling application. The properties in Assembly.GetExecutingAssembly() don't seem to be of much help either, pointing to ASP.NET Temporary Files.
Basically my question is what the best way to handle this would be. The template files should be a shared resource available to every application (and not copy/pasted into three Templates/ directories in each application), but I don't know which application will call it at a given time so I need to avoid hard-coding the file path to the templates folder. I'm missing something small but critical in how I'm trying to retrieve the template file, but I can't figure out exactly what.
Decide on a common, shared path available to all three sites and define that path in your web.config files, making sure that IIS is able to access that shared folder.

How to get the directory of database?

I am using the Microsoft database that is inside C:\wpf1\WpfApplication1\WpfApplication1 folder. When I update the database it always updates the one inside C:\wpf1\WpfApplication1\WpfApplication1\bin\Debug which I don't want.
How do I get the folder C:\wpf1\WpfApplication1\WpfApplication1 without typing this full name?
There is an article here about sql server compact edition
I dont think anything has changed in the newer releases although it is a while since i have used it.
|DataDirectory| works as follows
Your connection string would normally look like this
“Data Source = |DataDirectory|\Mydb.sdf”
To set the DataDirectory property, call the AppDomain.SetData method.
If you do not set the DataDirectory property, the following default rules will be applied to access the database folder:
For applications that are put in a folder on the user's computer, the database folder uses the application folder. (this is the default rule that applies when debugging and hence why the database in \bin\debug is the one that is updated)
For applications that are running under ClickOnce, the database folder uses the specific data folder that is created.
In the past i have done the following
Handle the SettingsLoaded event in settings.vb
Private Sub MySettings_SettingsLoaded(sender As Object, e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded
If Not Debugger.IsAttached Then
My.Settings.SQLCEConnectionString = "somefolder\somefile.sdf"
End If
End Sub
The directory C:\wpf1\WpfApplication1\WpfApplication1 is your project directory - its the one that the source code is in, but its not normally a directory that your application would usually be aware of or work with (for example if your application is installed to another PC then this directory simply won't exist).
The usual approach when working with databases or dependent files is to either:
Put the file in some other common location (such as in a folder on the C: drive)
Just have the application work with the copy of the file in the output (bin\Debug\) directory, i.e. the directory that the application will be installed to - you can change the properties of the item in your solution to have the item copied to the output directory, either all the time or only when the item in the solution directory is newer:
If you really want to use C:\wpf1\WpfApplication1\WpfApplication1 directory then the way to do it is to assume that this directory will always be 2 higher than the current working directory:
Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "..\\.."));
This of course makes 2 horrible assumptions, first that the current directory is the directory that the .exe is contained in, and secondly that the directory you want is always 2 higher than this directory - I strongly recommend that you find another way as this sort of logic is highly unlikely to work on an end-users PC.

How to determine whether an relative path points outside an given path

I have the following scenario (C#, WinForms). I have some kind of project file which is saved in some directory. The project file contains a reference to another file. This reference is relative from the place where the project file is saved.
Sample: The project file is saved under c:\projects\project.xyz. The other file is referenced as "\someotherdir\file.abc".
This works fine, but there may be the case someone tried to manipulate that relative path to something like "..\Windows\System32\file.abc". So there's a need to check whether the relative path points outside the path where the project is saved (it's a defined requirement, that all referenced files are inside the project path).
How to detect this scenario?
You could try using the following extension method:
public static bool IsChildOf(this string path, string parentPath)
{
return Path.GetFullPath(path).StartsWith(Path.GetFullPath(parentPath),
StringComparison.InvariantCultureIgnoreCase);
}
Not very pretty but I think it should work.
if (System.IO.Path.GetFullPath(path).IndexOf(projectPath, StringComparison.CurrentCultureIgnoreCase) == -1)
{
// naughty
}
Edited to be a good global citizen.
Windows has posix symlinks: ln -s c:\windows\system32\mshtml.dll c:\projects\project.xyz\innocent.txt. When your program opens c:\projects\project.xyz\innocent.txt you get c:\windows\system32\mshtml.dll. Does System.IO.Path.GetFullPath() work here?
POSIX also supports hardlinks. A file can have zero (when deleted), one, two, ten, one hundred filenames. And all are "The Filename", none more correct or less correct than any other.
Windows supports mounting folders into folders. Again, all names are correct.
You can solve this with filesystem permissions: Create a new user for your application. Give that user permissions to your project path. Do not give that user (or Everyone, or any groups the user is a member of) privileges to anything else in any filesystem. Let Microsoft's kernel team solve your problem for you.

Write to a File in Monotouch

How would I create and write to a file in a Monotouch iPhone app?
The file should persist between application launches, so I guess it has to be placed somewhere in the App bundle ( documents or resources?).
[Note: My response is pretty thorough because I don't know your level of understanding regarding app bundles or the structure of your iPhone app's sandboxed little world - apologies if I cover things you already know - I prefer to write a little too much than too little, and to add a bit of the why when discussing the how...]
You have a few options (of course). I'm assuming you're already familiar with .Net to some extent and that your question is more about how to do this the iPhone Way.
Every iPhone app (and you'll see the same thing for apps on OS X) is a "bundle" which isn't an executable in the traditional sense, but actually a folder hierarchy inside of which your app binary lives (along with resources, settings, etc.).
Because of how uber-sandboxed iPhone apps are, you don't have access to the shared folders you'd usually be able to use when doing desktop development (having, for example, a common Documents folder that lives under a user's home folder to which applications have access).
Instead, your app has its own folder hierarchy that's like its own personal set of the folders that would typically be shared across apps.
The easiest way to see what your app's folder structure looks like on the phone is to look at the folder the iPhone simulator uses for app installs, settings, blah blah blah. On my machine (I don't recall if this is configurable, but it's probably the same on your system), you can get to the folder by this path:
~/Library/Application Support/iPhone Simulator
Inside of that, there's a User/Applications folder that contains the apps you've installed to the simulator. Drill down into any one of those folders, and you can see the folder structure your app will have access to on the phone.
For storing files that you'd like persisted across app sessions, your app's Documents folder is the spot. It's not your only choice for creating files, but it's the right choice for this job. In addition to your files being properly stored, keeping them in the Documents folder will also get them backed up by iTunes when the user syncs.
With MonoTouch, you can get your app's Documents folder path with Environment.GetFolderPath(Environment.SpecialFolder.Personal);
If you'd like to test it out, this is some extremely simple code that'll write a file called "out.txt" to your app's Documents folder. This code also reads the contents of the file to show it was created - for further verification, go to the simulator's Applications folder, sort the app folders by the date they were modified, drill down into the most recently modified, and look inside its Documents folder - you'll find "out.txt" (you can't find your app's folder by name because, when your app is installed, it gets stuffed inside a folder with a name like "2B3CA854-FADB-4DDC-9732-0E61B3DD8D8C" - sorting the folders by the date they were modified will point you to the most recently modified app, which, in this case, is whatever app contains the following code):
// For this to function, don't forget "using System.IO;"
// If you're just playing around with this to see it work, place it inside
// your AppDelegate's "FinishedLaunching" method in main.cs
string path = Environment.GetFolderPath (Environment.SpecialFolder.Personal);
string filePath = Path.Combine(path, "out.txt");
// File.WriteAllText will create a file and then write text to it. If the
// file already exists, File.WriteAllText will overwrite it.
File.WriteAllText(filePath, "Howdy, world.");
// Now we prove it worked by reading the contents of the file and then
// printing them to the console...
string text = File.ReadAllText(filePath);
Console.WriteLine(text);
So, the only thing here that's really iPhone-specific is knowing that "Environment.SpecialFolder.Personal" maps to your app's Documents folder. Beyond that, it's .Net as usual.
And, again, this was probably overkill, but I wanted to answer sufficiently thoroughly for everybody who sees it.
The following How To from the Xamarin.iOS guide site has a few pointers to where to store your files:
http://docs.xamarin.com/guides/ios/application_fundamentals/working_with_the_file_system/
You can do something like this at runtime:
using (StreamWriter writer = new StreamWriter (Path.Combine (Environment.SpecialFolders.Documents, "yourfilename.ext"))) { }
and that will create the file. To open it for reading, use the same Path.Combine() but with StreamReader.

Categories

Resources