I am new to c#, I have made a function which creates a new folder with a time stamp everytime the console is run.
string newfolder = #"d:\Denby_Screenshots" + DateTime.Now.ToString(" yyyy-MM-dd-HH-mm-ss-fff");
if (!Directory.Exists(newfolder))
{
Directory.CreateDirectory(newfolder);
Console.WriteLine("Screenshot folder has been created");
}
I then would like this to be down to allow the screenshots to be saved into this newly created file.
static private Test_Criteria Block_Two(IWebDriver driver, Screenshot screenshot, string newfolder)
{
{
screenshot = ((ITakesScreenshot)driver).GetScreenshot();
screenshot.SaveAsFile("d:\\ScreenShot.png",System.Drawing.Imaging.ImageFormat.Png);
But for the life of me I am not sure how to do this would anyone be able to advise or have any good screenshots for me to be able to work from.
Thanks
If you are doing these two steps in one console context. Then simply, return newly created folder name to the calling function. And use that folder name (as string) to save files into.
Something like this:
SaveAsFile(Path.Combine(returnedFolderName, suggestedFileName).....
Like so:
screenshot.SaveAsFile(Path.Combine(newFolder,"screenshot.png", ImageFormat.Png);
And reconsider your folder structure, it would be extremely annoying to have a zillion folders in your root folder with just one file in each.
A better approach would be
newFolder = Path.Combine(Environment.SpecialFolder.MyPictures, "Screenshots",DateTime.Now.ToString("yyyyMMdd"));
And the target file name:
Path.Combine(newFolder, "Screenshot "+DateTime.Now.ToString("HH-mm-ss-fff")+".png");
Related
public void Save_Token(string _Token)
{
var Token_Location = #".\token.txt";
using (StreamWriter sw = new StreamWriter(Token_Location))
{
sw.WriteLine(_Token);
}
}
I tried to get the token from the api (json) and I deserialized and saved it. I would like to write to the file to save for later. But I want this application to be ran on anyone's PC. So I don't want to use the full path.
I also tried
Path.Combine(Environment.CurrentDirectory,Token_Location);
still nothing is written, unless I use the full path.
You can't guarantee that the current user has write access to the folder from where the file is executed. There is a special folder (APP_DATA) that applications are supposed to use when storing user data on a computer:
public void Save_Token(string _Token)
{
var tokenDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "YourCompanyOrOrganizationName");
var tokenFile = Path.Combine(tokenDirectory, "token.txt");
Directory.CreateDirectory(tokenDirectory);
File.WriteAllText(tokenFile, _Token);
}
Your file will then be stored in a path like "C:\Users\yourusername\AppData\Roaming\YourCompanyOrOrganizationName\token.txt"
It is generally a bad idea to use a relative path in software source code because the "current working directory" of the process that the relative path is relative to can change over the runtime of the application.
Activities like showing a file open dialog or using a third-party component can unexpectedly change the current working directory so that it is dangerous to assume a certain current working directory.
I am using the media plugin for xamarin forms (by james montemagno) and the actual taking of the picture and storing it works fine, I have debugged the creation of the image on the emulator and it is stored in
/storage/emulated/0/Android/data/{APPNAME}.Android/files/Pictures/{DIRECTORYNAME}/{IMAGENAME}
however in my app it will get a list of file names from an API I want to check if the image exists in that folder.
The following works fine on IOS
var documentsDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
string jpgFilename = System.IO.Path.Combine(documentsDirectory, App.IMAGE_FOLDER_NAME);
jpgFilename = System.IO.Path.Combine(jpgFilename, name);
I have tried the 2 following methods for getting it on android but both are incorrect
var documentsDirectory = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
string jpgFilename = System.IO.Path.Combine(documentsDirectory, App.IMAGE_FOLDER_NAME);
jpgFilename = System.IO.Path.Combine(jpgFilename, name);
Java.IO.File dir = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DataDirectory + "/" + App.IMAGE_FOLDER_NAME + "/" + name);
dir ends up as
/storage/emulated/0/data/{DIRECTORY}/{IMAGENAME}
jpgFileName ends up as /data/data/{APPNAME}.Android/files/{DIRECTORYNAME}/{IMAGENAME}
I dont want to hardcode anything in the paths but neither of these are right. I could not find anything in the GIT documentation for getting the file path except by looking at the path of the file created when taking a picture
The problem
I had the same kind of issue with Xamarin Media Plugin. For me, the problem is:
we don't really know where the plugin save the picture on android.
After reading all documentation I found, I just noted this:
... When your user takes a photo it will still store temporary data, but also if needed make a copy to the public gallery (based on platform). In the MediaFile you will now see a AlbumPath that you can query as well.
(from: Github plugin page)
so you can save your photo to your phone gallery (it will be public) but the path is known.
and we don't know what means "store the temporary data".
Solution
After investigating on how/where an app can store data, I found where the plugin stores photos on Android >> so I can generate back the full file names
In your Android app, the base path you are looking for is:
var basePath = Android.App.Application.Context.GetExternalFilesDir(null).AbsolutePath
It references your app's external private folder. It looks like that:
/storage/emulated/0/Android/data/com.mycompany.myapp/files
So finally to get your full file's path:
var fullPath = basePath + {DIRECTORYNAME} + {FILENAME};
I suggest you to make a dependency service, for instance 'ILocalFileService', that will expose this 'base path' property.
Please let me know if it works for you !
I resolved a similar problem. I wanted to collect all files for my app in a folder visible to all users.
var documentsDirectory = Android.OS.Environment.GetExternalStoragePublicDirectory(
Android.OS.Environment.DirectoryDocuments);
If you want to create Directory, add to your class using System.IO; and you have the same functions in a normal .NET application.
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
If you want to create files or directory, you can use PCLStorage.
public async Task<bool> CreateFileAsync(string name, string context)
{
// get hold of the file system
IFolder folder = FileSystem.Current.LocalStorage;
// create a file, overwriting any existing file
IFile file = await folder.CreateFileAsync(name,
CreationCollisionOption.ReplaceExisting);
// populate the file with some text
await file.WriteAllTextAsync(context);
return true;
}
to get the private path
var privatePath = file.Path;
to get the public Album path
var publicAlbumPath = file.AlbumPath;
se the documentation here https://github.com/jamesmontemagno/MediaPlugin
I have a log object that writes daily log files with a relative path. It's fairly simple (.NET 4.0, VS 2010).
public void LogLine(string txt)
{
DateTime dt = DateTime.Now;
if (CurrentDay != dt.Day)
{
string newFileName = "..\\Log\\" + programName + dt.Day + ".log";
fs = new FileStream(newFileName, FileMode.Create, FileAccess.Write);
sw = new StreamWriter(fs);
CurrentDay = dt.Day;
}
sw.WriteLine(txt);
}
This works well almost all the time. However, sometimes I get what seems to be a random DirectoryNotFoundException with a totally different path. For example, when I first run the program, it creates a file:
C:\MyFiles\Log\MyApp19.log
After using the program some and letting it run overnight so a new file and stream are created (at the first log after midnight), I come back to the DirectoryNotFoundException stating something like:
C:\MyFiles\MyOtherFiles\Resources\Log\MyApp20.log
The only thing that I can think of is: I use an OpenFileDialog and SaveFileDialog a couple times throughout the life of the software, and one of those open/save dialogs access a file within
C:\MyFiles\MyOtherFiles\Resources\SavedFiles\
So it seems to me that when I use the dialogs, I open/save something into the SavedFiles directory and when it creates the new log, the relative file path ..\ goes up to Resources (from SavedFiles), then can't find the directory Log within Resources and throws an exception. However, I can't reproduce the problem using dialogs, and I thought the relative path is relative to the executable? Can the Open/Save File Dialogs alter how the software calculates the relative file path? Anyone have any thoughts? Thanks for your time!
Alng i think that the following link can help you:
http://msdn.microsoft.com/en-us/library/system.windows.forms.filedialog.aspx
Pay attention to the following part:
Important:
If the user of your application changes the folder in the FileDialog, then the current working directory for your application is set to the location specified in the FileDialog. To prevent this, set the RestoreDirectory property to true.
Try to use the Microsoft proposed methodologies for paths as described in the above link.
This can help you also
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.executablepath.aspx
regards
A relative path always works on the current directory of the application. That can easily change, for example when you show a save dialog.
It is always better to create a path relative to your executable.
var assembly = Assembly.GetEntryAssembly() ?? Assembly.GetCallingAssembly();
var path = Path.GetDirectoryName(assembly.Location);
newFileName = Path.Combine(path, "..\\Log\\" + programName + dt.Day + ".log");
I'm making a guess that the application changes the current working directory at some point. As a result, on that basis, I'd use a fully-qualified path for the log file. You could use the assembly's startup path, eg Application.StartupPath, which should not change even if the app changes folders for some reason.
I am having an xml file like:
<CurrentProject>
// Elements like
// last opened project file to reopen it when app starts
// and more global project independend settings
</CurrentProject>
Now I asked myself wether I should deliver this xml file with above empty elements with the installer for my app or should I create this file on the fly on application start if it does not exist else read the values from it.
Consider also that the user could delete this file and that should my application not prevent from working anymore.
What is better and why?
UPDATE:
What I did felt ok for me so I post my code here :) It just creates the xml + structure on the fly with some security checks...
public ProjectService(IProjectDataProvider provider)
{
_provider = provider;
string applicationPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
_projectPath = Path.Combine(applicationPath,#"TBM\Settings.XML");
if (!File.Exists(_projectPath))
{
string dirPath = Path.Combine(applicationPath, #"TBM");
if (!Directory.Exists(dirPath))
Directory.CreateDirectory(dirPath);
using (var stream = File.Create(_projectPath))
{
XElement projectElement = new XElement("Project");
projectElement.Add(new XElement("DatabasePath"));
projectElement.Save(stream, SaveOptions.DisableFormatting);
}
}
}
In a similar scenario, I recently went for creating the initial file on the fly. The main reason I chose this was the fact that I wasn't depending on this file being there and being valid. As this was a file that's often read from/written to, there's a chance that it could get corrupted (e.g. if the power is lost while the file is being written).
In my code I attempted to open this file for reading and then read the data. If anywhere during these steps I encountered an error, I simply recreated the file with default values and displayed a corresponding message to the user.
I am using XNA and I want to save files to Vista's "Saved Games" folder.
I can get similar special folders like My Documents with Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) but I cannot find an equivalent for the Saved Games folder. How do I get to this folder?
http://msdn.microsoft.com/en-us/library/bb200105.aspx#ID2EWD
Looks like you'll need to use Microsoft.Xna.Framework.Storage and the StorageLocation class to do what you need to.
Currently, the title location on a PC
is the folder where the executable
resides when it is run. Use the
TitleLocation property to access the
path.
User storage is in the My Documents
folder of the user who is currently
logged in, in the SavedGames folder. A
subfolder is created for each game
according to the titleName passed to
the OpenContainer method. When no
PlayerIndex is specified, content is
saved in the AllPlayers folder. When a
PlayerIndex is specified, the content
is saved in the Player1, Player2,
Player3, or Player4 folder, depending
on which PlayerIndex was passed to
BeginShowStorageDeviceSelector.
There is no special folder const for it so just use System Variables. According to this Wikipedia article Special Folders, the saved games folder is just:
Saved Games %USERPROFILE%\saved games Vista
So the code would be:
string sgPath = System.IO.Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), "saved games"));
...
EDIT: If, as per the comments, localization is an issue and as per your question you still want access to the Saved Games folder directly rather than using the API, then the following may be helpful.
Using RedGate reflector we can see that GetFolderPath is implemented as follows:
public static string GetFolderPath(SpecialFolder folder)
{
if (!Enum.IsDefined(typeof(SpecialFolder), folder))
{
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, GetResourceString("Arg_EnumIllegalVal"), new object[] { (int) folder }));
}
StringBuilder lpszPath = new StringBuilder(260);
Win32Native.SHGetFolderPath(IntPtr.Zero, (int) folder, IntPtr.Zero, 0, lpszPath);
string path = lpszPath.ToString();
new FileIOPermission(FileIOPermissionAccess.PathDiscovery, path).Demand();
return path;
}
So maybe you think all i need is to create my own version of this method and pass it the folder id for Saved Games. That wont work. Those folder ids pre-Vista were actually CSIDLs. A list of them can be found here. Note the Note: however.
In releasing Vista, Microsoft replaced CLSIDLs with KNOWNFOLDERIDs. A list of KNOWNFOLDERIDs can be found here. And the Saved Games KNOWNFOLDERID is FOLDERID_SavedGames.
But you don't just pass the new const to the old, CLSIDL based, SHGetFolderPath Win32 function. As per this article, Known Folders, and as you might expect, there is a new function called SHGetKnownFolderPath to which you pass the new FOLDERID_SavedGames constant and that will return the path to the Saved Games folder in a localized form.
The easiest way I found to get the Saved Games path was to read the Registry value likes this:
var defaultPath = Path.Combine(Environment.GetEnvironmentVariable("USERPROFILE"), "Saved Games");
var regKey = "HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders";
var regKeyValue = "{4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4}";
var regValue = (string) Registry.GetValue(regKey, regKeyValue, defaultPath);
I changed the location of my Saved Games via the Shell multiple times and the value of this key changed each time. I use the USERPROFILE/Saved Games as a default because I think that will work for the default circumstance where someone has never changed the location.