Cannot load nlog.config in Xamarin - c#

I cannot read nlog.config file in asset folder of android platform
NLog.LogManager.Configuration = new XmlLoggingConfiguration("NLog.config");
How to read nlog file and also this file is in android asset.

You can also make use of Xamarin resource. Put the NLog.config file into the library project, then edit file's properties - change the build action to embedded resource.
public static Stream GetEmbeddedResourceStream(Assembly assembly, string resourceFileName)
{
var resourcePaths = assembly.GetManifestResourceNames()
.Where(x => x.EndsWith(resourceFileName, StringComparison.OrdinalIgnoreCase))
.ToList();
if (resourcePaths.Count == 1)
{
return assembly.GetManifestResourceStream(resourcePaths.Single());
}
return null;
}
var nlogConfigFile = GetEmbeddedResourceStream(myAssembly, "NLog.config");
if (nlogConfigFile != null)
{
var xmlReader = System.Xml.XmlReader.Create(nlogConfigFile);
NLog.LogManager.Configuration = new XmlLoggingConfiguration(xmlReader, null);
}
See also: https://github.com/NLog/NLog/wiki/Explicit-NLog-configuration-loading#loading-nlog-configuration-from-xamarin-resource

you could also try to use this (nlog.config file with a Build Action as an AndroidAsset):
NLog.LogManager.Configuration = new XmlLoggingConfiguration (XmlTextReader.Create(Assets.Open ("NLog.config")), null);
refer to:
https://github.com/NLog/NLog/blob/master/src/NLog/Config/LoggingConfigurationFileLoader.cs#L101-L120

You can add an extension method to your context class that gets you the required asset as a stream:
public static class Utils
{
public static Stream GetFromAssets(this Context context, string assetName)
{
AssetManager assetManager = context.Assets;
Stream inputStream;
try
{
using (inputStream = assetManager.Open(assetName))
{
return inputStream;
}
}
catch (Exception e)
{
return null;
}
}
}
And then in your activity context access it like:
var Asset= context.GetFromAssets("AssetName");
Note that this will return a System.IO.Stream.
Good luck
Revert in case of queries.

For Xamarin Android "NLog.config" (in this casing) in the assets folder will be loaded automatically. If the file name is different, then use:
LogManager.Configuration = new XmlLoggingConfiguration("assets/someothername.config");

Thanks for your response. I resolved this issue by setting autoReload="false" throwExceptions="false". Due to these two my config file was not visible. I dont know how they affect the file visibility but setting above two to false i can get config file now
Thanks,

Related

Android: How do I construct *full* path to pass to Intent.CreateChooser

Trying to make Android chooser to display available actions for user to launch a PDF file which is stored in my local folder.
When I pass the file name like /data/user/0/myappappname/files/output.pdf , (which exsists, of course), I get a nice chooser with all the apps that can accept a pdf file. But when I pick any of them, I get an error (from external app) The document path is not valid. No exception is thrown.
Then I tried (for testing purposes) to set fname to something like /storage/emulated/0/Download/TLCL.pdf (file also exists), and everything works fine.
At first, I thought that this has something to do with file permissions (since first path is private to my app), but then I found flag ActivityFlags.GrantReadUriPermission built exactly for purpose of temporarily granting file access to other apps. Still same results.
Since this is a Xamarin.forms project, I am limited in choice of file creation locations (I use PCLStorage, which always writes to app-private, local folder), so I don't have an option of generating files in /Documents, /Downloads etc.
I am obviously doing something wrong. Any ideas appreciated.
Is there an option to get full path from system, including the /storage/emulated/0 part (or whatever that would be on other devices)? Maybe that would help?
Piece of code:
(mimeType is defined as "application/pdf" earlier)
public async Task<bool> LaunchFile(string fname, string mimeType)
{
var uri = Android.Net.Uri.Parse("file://" + fname );
var intent = new Intent(Intent.ActionView);
intent.SetDataAndType(uri, mimeType);
intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask | ActivityFlags.GrantReadUriPermission );
try
{
Forms.Context.StartActivity(Intent.CreateChooser(intent, "ChooseApp"));
return true;
}
catch (Exception ex)
{
Debug.WriteLine("LaunchFile: " + ex.Message);
return false;
}
My solution to this, which may not be exactly what you want, is to generate a file (in my case a zip file), export it to a public folder, and use that file for the chooser.
Using these:
private readonly string PublicDocsPath = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath + "/AppName";
private readonly string PrivateDocsPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData);
and some basic functions:
public Stream GetOutputStream(string destFilePath)
{
string destFolderPath = Path.GetDirectoryName(destFilePath);
if (!Directory.Exists(destFolderPath))
Directory.CreateDirectory(destFolderPath);
return new FileStream(destFilePath, FileMode.Create, FileAccess.Write, FileShare.None);
}
public Stream GetInputStream(string sourceFilePath)
{
if (!File.Exists(sourceFilePath)) throw new FileNotFoundException();
string sourceFolderPath = Path.GetDirectoryName(sourceFilePath);
return new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
}
You can copy your file to your public folder (or subfolders, you just have to assemble the path) and use that file for your chooser:
public void SendEmail(string subject, string body, string recipient, string mimeType, string attachmentFilePath, string activityTitle)
{
var emailIntent = new Intent(Intent.ActionSendMultiple);
if (string.IsNullOrEmpty(subject)) throw new ArgumentException();
emailIntent.PutExtra(Intent.ExtraSubject, subject);
if (!string.IsNullOrEmpty(recipient))
emailIntent.PutExtra(Intent.ExtraEmail, new[] { recipient });
if (!string.IsNullOrEmpty(body))
emailIntent.PutExtra(Intent.ExtraText, body);
if (!string.IsNullOrEmpty(attachmentFilePath))
{
var file = new Java.IO.File(attachmentFilePath);
file.SetReadable(true, true);
var uri = Android.Net.Uri.FromFile(file);
emailIntent.PutParcelableArrayListExtra(Intent.ExtraStream, new List<IParcelable>(){uri});
}
emailIntent.SetType(mimeType);
_activity.StartActivity(Intent.CreateChooser(emailIntent, activityTitle));
}
This chooser specifically lets the user send their file via email or google drive , but you can assemble it however you want. The attachmentFilePath of this function is the same as the string passed into the GetOutputStream function above.
we're using Acr.IO rather than PCLStorage and I recall that has a property that'll return the fullpath for you.
The code we're using is below, but I wonder if you're simply missing "file://" off the start of your path, as I noticed thats in our code, as well as this previous stackoverflow answer to a similar question as this one, open a PDF in Xamarin.Forms (Android)
We're using a dependency FileService on Android and using this code to open PDFs:
public void OpenNatively(string filePath) {
Android.Net.Uri uri;
if (filePath.StartsWithHTTP()) {
uri = Android.Net.Uri.Parse(filePath);
}
else {
uri = Android.Net.Uri.Parse("file:///" + filePath);
}
Intent intent = new Intent(Intent.ActionView);
var extension = filePath.Substring(filePath.LastIndexOf(".")+1);
if (extension == "ppt" || extension == "pptx") {
extension = "vnd.ms-powerpoint";
}
var docType = "application/" + extension;
intent.SetDataAndType(uri, docType);
intent.SetFlags(ActivityFlags.ClearWhenTaskReset | ActivityFlags.NewTask);
try {
Xamarin.Forms.Forms.Context.StartActivity(intent);
}
catch (Exception e) {
Toast.MakeText(Xamarin.Forms.Forms.Context, "No Application found to view " + extension.ToUpperInvariant() + " files.", ToastLength.Short).Show();
}
}

UWP Check If File Exists

I am currently working on a Windows 10 UWP App.
The App needs to Check if a certain PDF File exists called "01-introduction", and if so open it.
I already have the code for if the file does not exist.
The Code Below is what i currently have:
try
{
var test = await DownloadsFolder.CreateFileAsync("01-Introduction.pdf", CreationCollisionOption.FailIfExists);
}
catch
{
}
This code Does not work correctly because to check if the file exists here, I attempt to create the file. However if the file does not already exist an empty file will be created. I do not want to create anything if the file does not exist, just open the PDF if it does.
If possible, i would like to look inside a folder which is in the downloads folder called "My Manuals".
Any help would be greatly appreciated.
public async Task<bool> IsFilePresent(string fileName)
{
var item = await ApplicationData.Current.LocalFolder.TryGetItemAsync(fileName);
return item != null;
}
But not support Win8/WP8.1
https://blogs.msdn.microsoft.com/shashankyerramilli/2014/02/17/check-if-a-file-exists-in-windows-phone-8-and-winrt-without-exception/
There are two methods
1) You can use StorageFolder.GetFileAsync() as this is also supported by Windows 8.1 and WP 8.1 devices.
try
{
StorageFile file = await DownloadsFolder.GetFileAsync("01-Introduction.pdf");
}
catch
{
Debug.WriteLine("File does not exits");
}
2) Or you can use FileInfo.Exists only supported for windows 10 UWP.
FileInfo fInfo = new FileInfo("01-Introduction.pdf");
if (!fInfo.Exists)
{
Debug.WriteLine("File does not exits");
}
System.IO.File.Exists is UWP way too. I test now in Windows IOT. it just works.
This helped me in my case:
ApplicationData.Current.LocalFolder.GetFileAsync(path).AsTask().ContinueWith(item => {
if (item.IsFaulted)
return; // file not found
else { /* process file here */ }
});
This worked for me running my UWP C# app on Windows 10...
StorageFolder app_StorageFolder = await StorageFolder.GetFolderFromPathAsync( #App.STORAGE_FOLDER_PATH );
var item = await app_StorageFolder.TryGetItemAsync(relative_file_pathname);
return item != null;
public override bool Exists(string filePath)
{
try
{
string path = Path.GetDirectoryName(filePath);
var fileName = Path.GetFileName(filePath);
StorageFolder accessFolder = StorageFolder.GetFolderFromPathAsync(path).AsTask().GetAwaiter().GetResult();
StorageFile file = accessFolder.GetFileAsync(fileName).AsTask().GetAwaiter().GetResult();
return file != null;
}
catch
{
return false;
}
}
You can use System.IO.File.
Example:
// If file located in local folder. You can do the same for other locations.
string rootPath = ApplicationData.Current.LocalFolder.Path;
string filePath = Path.Combine(rootPath, "fileName.pdf");
if (System.IO.File.Exists(filePath))
{
// File exists
}
else
{
// File doesn't exist
}
I'm doing a Win10 IoT Core UWP app and I have to check the file length instead of "Exists" because CreateFileAsync() already creates an empty file stub immediately. But I need that call before to determine the whole path the file will be located at.
So it's:
var destinationFile = await ApplicationData.Current.LocalFolder.CreateFileAsync("MyFile.wow", ...);
if (new FileInfo(destinationFile.Path).Length > 0)
return destinationFile.Path;
In this way System.IO.File.Exists(filePath) I cannot test DocumentLibrary
because KnownFolders.DocumentsLibrary.Path return empty string
Next solution is very slow await DownloadsFolder.GetFileAsync("01-Introduction.pdf")
IMHO the best way is collect all files from folder and check the file name exist.
List<StorageFile> storageFileList = new List<StorageFile>();
storageFileList.AddRange(await KnownFolders.DocumentsLibrary.GetFilesAsync(CommonFileQuery.OrderByName));
bool fileExist = storageFileList.Any(x => x.Name == "01-Introduction.pdf");
CreateFileSync exposes an overload that let's you choose what to do if an existing file with the same name has been found in the directory, as such:
StorageFile localDbFile = await DownloadsFolder.CreateFileAsync(LocalDbName, CreationCollisionOption.OpenIfExists);
CreationCollisionOption is the object that you need to set up. In my example i'm opening the file instead of creating a new one.
Based on another answer here, I like
public static async Task<bool> DoesFileExist(string filePath) {
var directoryPath = System.IO.Path.GetDirectoryName(filePath);
var fileName = System.IO.Path.GetFileName(filePath);
var folder = await StorageFolder.GetFolderFromPathAsync(directoryPath);
var file = await folder.TryGetItemAsync(fileName);
return file != null;
}
You can use the FileInfo class in this case. It has a method called FileInfo.Exists() which returns a bool result
https://msdn.microsoft.com/en-us/library/system.io.fileinfo.exists(v=vs.110).aspx
EDIT:
If you want to check for the files existence, you will need to create a StorageFile object and call one of the GetFile.... methods. Such as:
StorageFile file = new StorageFile();
file.GetFileFromPathAsync("Insert path")
if(file == null)
{
/// File doesn't exist
}
I had a quick look to find the download folder path but no joy, but the GetFile method should give you the answer your looking for
On Window 10, for me, this is the most "elegant" way:
private static bool IsFileExistent(StorageFile file)
{
return File.Exists(Path.Combine(file.Path));
}
Or, as an extension if you prefer and will use it widely:
static class Extensions
{
public static bool Exists(this StorageFile file)
{
return File.Exists(Path.Combine(file.Path));
}
}

HttpContext.Current.Request.Url.IsFile Returns False When Url is ASPX Page

I'm hitting a local URL of the form: http://localhost/example.dev/eu/default.aspx.
My goal is to determine when the request is an aspx file inside of the global.asax file, and subsequently do stuff if it is an aspx file (and only an aspx file) using:
HttpContext.Current.Request.Url.IsFile
It's consistently resolving to false however and I'm not sure why. My complete global.asax code is:
if(HttpContext.Current.Request.Url.IsFile)
{
if(File.Exists(HttpContext.Current.Request.Url.LocalPath))
{
if(new FileInfo(HttpContext.Current.Request.Url.LocalPath).Extension.Equals("aspx"))
{
DoSomethingWithThePagesURL();
}
}
}
Did you take a look at the Documentation for IsFile Property?. It seems very clear from the documentation that Http: is not File:.
The IsFile property is true when the Scheme property equals UriSchemeFile.
DotNetFiddle Example
using System;
public class Program
{
public static void Main()
{
Uri uriAddress2 = new Uri("file://server/filename.ext");
Console.WriteLine(uriAddress2.LocalPath);
Console.WriteLine("Uri {0} a UNC path", uriAddress2.IsUnc ? "is" : "is not");
Console.WriteLine("Uri {0} a local host", uriAddress2.IsLoopback ? "is" : "is not");
Console.WriteLine("Uri {0} a file", uriAddress2.IsFile ? "is" : "is not");
}
}
Results:
\server\filename.ext
Uri is a UNC path
Uri is not a local host
Uri is a file
I use Nuget package walter.web.firewall that inject a IPageRequest in each request, this contains access to the requests underlying resource and will provide access via IPageRequest.LocalFile
However if you do need a firewall and it has been a while since this was asked, and lot's of framework changes have taken place since the question was asked so let my try and answer it in a way that uses no framework classes hoping it will work for all that try and implement it in the future.
here's the code:
public enum FileLocation
{
NotSet,
Disk,
Resource,
}
private static readonly string[] FileExtenstions = new[] {
".js"
,".ts"
,".vue"
,".css"
,".jpg"
,".png"
,".gif"
,".ico"
,".svg"
,".ttf"
,".eot"
,".ttf"
,".woff"
,".woff2"
,".mp4"
,".mp3"
,".emf"
};
public FileLocation IsMappedTo(Uri uri)
{
if (uri is null)
{
throw new ArgumentNullException(nameof(uri));
}
//make sure we support .net default URI contract
if (uri.IsFile)
return FileLocation.Disk;
//now assume you are looking in a web application
var path = uri.AbsolutePath;
if (path.Length == 0 || path.Equals("/",StringComparison.Ordinal) || path.Length< FileExtenstions.Min(s=>s.Length))
return FileLocation.NotSet;
//get the directory normally one would use IWebHostEnvironment.ContentRootPath different versions .net will have other methods
var dir = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
//get all resources names from the assembly hosting this class out side if the loop from this assembly you can also use
//you can also use GetManifestResourceNames() to use the web application's assembly
var resourceNames = new HashSet<string>(this.GetType().Assembly.GetManifestResourceNames());
var entryAssembly = Assembly.GetEntryAssembly();
if (entryAssembly != null && entryAssembly != this.GetType().Assembly)
{
foreach (var entry in entryAssembly.GetManifestResourceNames())
{
if (string.IsNullOrEmpty(entry))
resourceNames.Add(entry);
}
}
for (var i = 0; i < FileExtenstions.Length; i++)
{
if (FileExtenstions[i].Equals(path[FileExtenstions[i].Length..], StringComparison.OrdinalIgnoreCase) || path.Contains(FileExtenstions[i], StringComparison.OrdinalIgnoreCase))
{
//exists on disk
if (File.Exists(Path.Combine(dir, path.Replace("/", #"\"))))
return FileLocation.Disk;
//has a file as an embedded resource with the same name (ignores the path) so you might have duplicates names
if (resourceNames.Any(a => a.EndsWith(path.Split('/')[^1], StringComparison.OrdinalIgnoreCase)))
return FileLocation.Resource;
}
}
return FileLocation.NotSet;
}

Copy a file in a new folder

I have a problem coping a file. I need to copy a .db file and put it in a new folder (called "directory",selected previously with FolderPicker).
The code that i have is: (this is for a store app for Windows 8.1)
try{
StorageFile newDB = await StorageFile.GetFileFromPathAsync(directory);
StorageFile originalDB = await StorageFile.GetFileFromPathAsync(Path.Combine(Windows.Storage.ApplicationData.Current.LocalFolder.Path, "AFBIT.db"));
await newDB.CopyAndReplaceAsync(originalDB);
}
catch(Exception ex){
}
I have a exception in neDB, and said "Value does not fall within the expected range."
I dont know another way to copy a file in xaml, if u know what is the problem or another way to do this i llbe very grateful.
I have something similar that I currently use when copying a file CopyFileAsync method I have created see if this can help you in regards to refactoring your code to a working model
public static async Task CopyFileAsync(string sourcePath, string destinationPath)
{
try
{
using (Stream source = File.Open(sourcePath, FileMode.Open))
{
using (Stream destination = File.Create(destinationPath))
{
await source.CopyToAsync(destination);
}
}
}
catch (IOException io)
{
HttpContext.Current.Response.Write(io.Message); //I use this within a web app change to work for your windows app
}
}
I'm not sure what your truly inquiring but I believe your attempting is:
public static bool CopyFile(string source, string destination)
{
if(!File.Exist(source))
return false;
if(string.IsNullOrEmpty(destination))
return false;
try
{
using(var reader = File.Open(source))
using(var writer = File.Create(destination))
reader.CopyTo(writer);
return true;
}
catch(IOException ex) { return false; }
}
Bare in mind this will eat your exception, then return false if it fails at any point for any reason.
That would essentially copy the file, I noticed that your trying to read your local application folder. Be careful, as it often requires Administrator Privileges when it resides in several locations within the Operating System.

c# - why always null get resource embedded file in sfx folder?

why always get null get resource embedded file in my project 'Kriptografi'. My folder is sfx. I tried file in build action 'embedded resource'. Anyone can resolve it ?
Thanks
void test()
{
var ConfigXml = "Kriptografi.sfx.Config.xml";
Stream cfg = Assembly.GetExecutingAssembly().GetManifestResourceStream(ConfigXml);
if (cfg == null)
{
MessageBox.Show("Nothing");
}
else
{
MessageBox.Show("Exist");
}
}

Categories