How to load images from resources with GetManifestResourceStream? - c#

How to load images from Resources, please? Some of my images are located inside a folder.
My image is saved as Resource (cf. Build Action). I don't use a .resx file.
I'm able to retrieve the list of all my resources with the help of this function:
public static string[] GetResourceNames()
{
var asm = Assembly.GetEntryAssembly();
string resName = asm.GetName().Name + ".g.resources";
using (var stream = asm.GetManifestResourceStream(resName))
using (var reader = new System.Resources.ResourceReader(stream))
{
return reader.Cast<DictionaryEntry>().Select(entry => (string)entry.Key).ToArray();
}
}
but I'm not able to load the resource (an image in my case).
Here are my tests:
string[] resourceNames = GetResourceNames();
Assembly assembly = Assembly.GetExecutingAssembly();
string projectName = assembly.GetName().Name;
string gresourceName = assembly.GetName().Name + ".g.resources";
//string gresourceName = assembly.GetName().Name + ".Properties.Resources";
var rm = new System.Resources.ResourceManager(gresourceName, typeof(Resources).Assembly);
var list = resourceNames.OrderBy(q => q).ToList(); //sort
//get all png images
foreach (string resourceName in list)
{
if (resourceName.EndsWith(".png"))
{
try
{
Console.WriteLine(resourceName.ToString());
//var test = (Bitmap)rm.GetObject(resourceName);
Stream imageStream = assembly.GetManifestResourceStream(gresourceName + "." + resourceName);
}
catch (Exception ex) {
Console.WriteLine("EXCEPTION: " + ex.Message);
}
}
}
In my case:
assembly = "VisualStudioTest"
resourceName = "testImages/add_32x32.png"
I've tried all combinations without success.
By example:
assembly.GetManifestResourceStream("VisualStudioTest.Properties.Resources.testImages.add_32x32.png")
assembly.GetManifestResourceStream("VisualStudioTest.g.resources.testImages.add_32x32.png")

According to Build actions page, Resource Build Type is for WPF projects. Are you working on a WPF project?
Using Embedded Resources instead would look like this:
var asm = Assembly.GetEntryAssembly();
foreach (string resourceName in asm.GetManifestResourceNames())
{
if (resourceName.EndsWith(".png"))
{
try
{
Console.WriteLine(resourceName.ToString());
Stream imageStream = assembly.GetManifestResourceStream(resourceName);
}
catch (Exception ex)
{
Console.WriteLine("EXCEPTION: " + ex.Message);
}
}
}

One trick I use in my own code is to query the resource names to match the short file name I'm looking for (e.g. "add_32x32.png") and just use that fully qualified name to pull the image.
private Image fromResource(string shortFileName)
{
var asm = GetType().Assembly;
var resource =
asm
.GetManifestResourceNames()
.First(_ => _.Contains(shortFileName));
using (var stream = asm.GetManifestResourceStream(resource))
{
return new Bitmap(stream);
}
}

Related

How to access embedded resources inside a merged DLL?

I have managed to merge DLL files as embedded resource to one DLL, using AssemblyResolve event, but when I try to use that Dll at another console application, I do not have access inside the embedded resources this merged Dll has. For example, this merged Dll contains another Dll of a class library I need to use, and I want to access public methods/interfaces etc.. that this class library has, but it seems I cannot access them from this merged Dll. How can this issue be resolved ?
static Dictionary<string, Assembly> dic = null;
static void Main(string[] args)
{
var filesList = Directory.EnumerateFiles( //path to Resources folder inside console application, which holds all DLLs that are set as embedded resources );
foreach (var file in filesList)
{
var fname = Path.GetFileNameWithoutExtension(file);
var embRes = "ConsoleAppTest.Resources." + fname + ".dll";
Console.WriteLine(embRes);
Load(embRes, fname + ".dll");
}
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
Console.ReadKey();
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
return GetAssembly(args.Name);
}
static void Load(string embeddedResource, string fileName)
{
if (dic == null)
dic = new Dictionary<string, Assembly>();
byte[] assemblyData = null;
Assembly asm = null;
Assembly curAsm = Assembly.GetExecutingAssembly();
using (Stream stream = curAsm.GetManifestResourceStream(embeddedResource))
{
// Either the file is not existed or it is not mark as embedded resource
if (stream == null)
throw new Exception(embeddedResource + " is not found in Embedded Resources.");
// Get byte[] from the file from embedded resource
assemblyData = new byte[(int)stream.Length];
stream.Read(assemblyData, 0, (int)stream.Length);
try
{
asm = Assembly.Load(assemblyData);
// Add the assembly/dll into dictionary
dic.Add(asm.FullName, asm);
Console.WriteLine(asm.FullName);
return;
}
catch
{
// Purposely do nothing
// Unmanaged dll or assembly cannot be loaded directly from byte[]
// Let the process fall through for next part
}
}
bool fileOk = false;
string tempFile = "";
//load unmanaged assemblies
using (SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider())
{
string fileHash = BitConverter.ToString(sha1.ComputeHash(assemblyData)).Replace("-", string.Empty); ;
tempFile = Path.GetTempPath() + fileName;
if (File.Exists(tempFile))
{
byte[] bb = File.ReadAllBytes(tempFile);
string fileHash2 = BitConverter.ToString(sha1.ComputeHash(bb)).Replace("-", string.Empty);
if (fileHash == fileHash2)
{
fileOk = true;
}
else
{
fileOk = false;
}
}
else
{
fileOk = false;
}
}
if (!fileOk)
{
System.IO.File.WriteAllBytes(tempFile, assemblyData);
}
asm = Assembly.LoadFile(tempFile);
dic.Add(asm.FullName, asm);
Console.WriteLine(asm.FullName);
}
static Assembly GetAssembly(string assemblyFullName)
{
if (dic == null || dic.Count == 0)
return null;
if (dic.ContainsKey(assemblyFullName))
return dic[assemblyFullName];
return null;
}
This console application is in .NET Framework 4.5.1 and when I build the solution, it produces an .exe file. Then I change the output type of the project to class library, to get a Dll instead of exe and build it again. After I get this merged Dll, ConsoleAppTest.dll, I add a reference to it at another test project, but I cannot access the dll that ConsoleAppTest has inside. For example, if it has ClientLibrary.dll inside, I want to access public methods/interfaces of this ClientLibrary.dll
using ConsoleAppTest;
//code to access public methods/interfaces of a dll that is inside ConsoleAppTest.dll included in using statement above

Get files from a folder that I have created in Xamarin.Android

I want get all files from an external storage folder(wall_e_imgs)..Here are codes-
public void getImages()
{
var path1 = Android.OS.Environment.ExternalStorageDirectory.AbsolutePath.ToString();
string path = System.IO.Path.Combine(path1, "wall_e_imgs");
//var files= System.IO.Directory.GetFiles(Android.OS.Environment.ExternalStorageDirectory.ToString() + "wall_e_imgs");
//var files = System.IO.Directory.GetFiles(path);
//string path = Android.OS.Environment.ExternalStorageDirectory.ToString() + "/wall_e_imgs";
//File directory=new File(path);
Java.IO.File directory = new Java.IO.File(path);
Java.IO.File[] files = directory.ListFiles();//always count is 0 even though there are lot files there
foreach (var i in files)
{
FileInfo info = new FileInfo(i.Name);
if (info.Name.Contains("Wall_e"))
{
di.Add(new DownloadedImages { Path1 = info.DirectoryName, Name1 = info.FullName });
}
}
}
But it always give 0 files even though there are lot of files.
Try this
var folder = Android.OS.Environment.ExternalStorageDirectory + Java.IO.File.Separator + "yourfoldername";
if (!Directory.Exists(folder))
Directory.CreateDirectory(folder);
var filesList = Directory.GetFiles(folder);
foreach (var file in filesList)
{
var filename = Path.GetFileName(file);
}
Try something like this:
// Use whatever folder path you want here, the special folder is just an example
string folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "wall_e_imgs");
if (Directory.Exists(folderPath))
{
var files = Directory.EnumerateFiles(folderPath);
foreach (var file in files)
{
// Do your stuff
}
}
Please note that this uses the Directory class from System.IO, not Java.IO
ffilelist will contain a list of mp3 files in "/storage/emulated/0/Music/"
string phyle;
string ffilelist = "";
public void listfiles()
{
try
{
var path1 = "/storage/emulated/0/Music/";
var mp3Files = Directory.EnumerateFiles(path1, "*.mp3", SearchOption.AllDirectories);
foreach (string currentFile in mp3Files)
{
phyle = currentFile;
ffilelist = ffilelist + "\n" + phyle;
}
//playpath(phyle); // play the last file found
}
catch (Exception e9)
{
Toast.MakeText(ApplicationContext, "ut oh\n"+e9.Message , ToastLength.Long).Show();
}
}

How to copy file from one library to another library using CSOM?

I need to copy a particular file from one library to another library.
At first, need to check if file is existing in that library.
If Existing, then need to overwrite file content and new sharepoint version should be updated for that document.
I need to do this using c# CSOM and sharepoint version is 2013.
Thanks in advance :)
public static void CopyDocuments(string srcUrl, string destUrl, string srcLibrary, string destLibrary, Login _login)
{
// set up the src client
SP.ClientContext srcContext = new SP.ClientContext(srcUrl);
srcContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
srcContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// set up the destination context (in your case there is no needs to create a new context, because it would be the same library!!!!)
SP.ClientContext destContext = new SP.ClientContext(destUrl);
destContext.AuthenticationMode = SP.ClientAuthenticationMode.FormsAuthentication;
destContext.FormsAuthenticationLoginInfo = new SP.FormsAuthenticationLoginInfo(_login.UserName, _login.Password);
// get the list and items
SP.Web srcWeb = srcContext.Web;
SP.List srcList = srcWeb.Lists.GetByTitle(srcLibrary);
SP.ListItemCollection col = srcList.GetItems(new SP.CamlQuery());
srcContext.Load(col);
srcContext.ExecuteQuery();
// get the new list
SP.Web destWeb = destContext.Web;
destContext.Load(destWeb);
destContext.ExecuteQuery();
foreach (var doc in col)
{
try
{
if (doc.FileSystemObjectType == SP.FileSystemObjectType.File)
{
// get the file
SP.File f = doc.File;
srcContext.Load(f);
srcContext.ExecuteQuery();
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
if (doc.FileSystemObjectType == SP.FileSystemObjectType.Folder)
{
// load the folder
srcContext.Load(doc);
srcContext.ExecuteQuery();
// get the folder data, get the file collection in the folder
SP.Folder folder = srcWeb.GetFolderByServerRelativeUrl(doc.FieldValues["FileRef"].ToString());
SP.FileCollection fileCol = folder.Files;
// load everyting so we can access it
srcContext.Load(folder);
srcContext.Load(fileCol);
srcContext.ExecuteQuery();
foreach (SP.File f in fileCol)
{
// load the file
srcContext.Load(f);
srcContext.ExecuteQuery();
string[] parts = null;
string id = null;
if (srcLibrary == "My Files")
{
// these are doc sets
parts = f.ServerRelativeUrl.Split('/');
id = parts[parts.Length - 2];
}
else
{
id = folder.Name;
}
// build new location url
string nLocation = destWeb.ServerRelativeUrl.TrimEnd('/') + "/" + destLibrary.Replace(" ", "") + "/" + id + "/" + f.Name;
// read the file, copy the content to new file at new location
SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(srcContext, f.ServerRelativeUrl);
SP.File.SaveBinaryDirect(destContext, nLocation, fileInfo.Stream, true);
}
}
}
catch (Exception ex)
{
Log("File Error = " + ex.ToString());
}
}
}
Source: https://sharepoint.stackexchange.com/questions/114033/how-do-i-move-files-from-one-document-library-to-another-using-jsom
I strongly advise against using the approach suggested by Nikerym. You don't want to download the bytes only to upload them unmodified. It's slow and error-prone. Instead, use the built-in method provided by the CSOM API.
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt162553(v=office.15)?redirectedfrom=MSDN
var srcPath = "https://YOUR.sharepoint.com/sites/xxx/SitePages/Page.aspx";
var destPath = $"https://YOUR.sharepoint.com/sites/xxx/SitePages/CopiedPage.aspx";
MoveCopyUtil.CopyFileByPath(ctx, ResourcePath.FromDecodedUrl(srcPath), ResourcePath.FromDecodedUrl(destPath), false, new MoveCopyOptions());
ctx.ExecuteQuery();
You can configure the override behavior by adjusting the 4th and 5th arguments of the function signature.
[...]
bool overwrite,
MoveCopyOptions options
https://learn.microsoft.com/en-us/previous-versions/office/sharepoint-server/mt844930(v=office.15)

how to get multiple files path in an array

i want to upload multiple pdf files in one file upload control in asp.net and then merg it ,
this is already done when i pass static path and file name
how to do that dynamically
my code is here
if (FileUpload1.HasFile)
{
try
{
HttpFileCollection uploadedVideoFiles = Request.Files;
// Get the HttpFileCollection
for (int i = 0; i < uploadedVideoFiles.Count; i++)
{
HttpPostedFile hpfiles = uploadedVideoFiles[i];
string fname = Path.GetFileName(hpfiles.FileName);
if (hpfiles.ContentLength > 0)
{
hpfiles.SaveAs(Server.MapPath("~/Images/") + Path.GetFileName(hpfiles.FileName));
hpfiles.SaveAs(Server.MapPath(Path.Combine(#"~/Images/", fname)));
string filepath = Server.MapPath(#"~/Images/");
string path = filepath + fname;
}
}
String[] files = #"C:\ENROLLDOCS\A1.pdf,C:\ENROLLDOCS\A#.pdf".Split(',');
MergeFiles(#"C:\ENROLLDOCS\New1.pdf", files);// merg is a method which merg 2 or more than 2 documents
}
catch (Exception ex)
{
Label1.Text = "The file could not be uploaded. The following error occured: " + ex.Message;
}
}
You will need to collect values of path in a List<string> and then pass the result to MergeFiles().
I don't quite follow your code (you'll need to clean it up a bit), but what you need is basically this:
var fileNames =
uploadedVideoFiles.
Select(uvf => {
var fileName = Path.GetFileName(hpfiles.FileName);
var destinatonPath = Path.Combine(Server.MapPath("~/images"), fileName);
uvf.SaveAs(destinatonPath);
return destinationPath;
}).
ToArray();
MergeFiles(#"C:\ENROLLDOCS\New1.pdf", fileNames);
Beware of duplicating file names in ~/images, though.

Web API handle uploaded files for delete

ok I have this code that handle a file been upload through a simple web form
CustomMultipartFormDataStreamProvider provider = new CustomMultipartFormDataStreamProvider(#"C:\inetpub\wwwroot\myapp\Images");
//var provider = new MultipartFormDataStreamProvider(#"C:\inetpub\wwwroot\myapp\Images");
var Image = "";
var Dir = "";
var CurrentPath = "";
string UploadType = "";
string ImageName = "";
// Read the form data.
await Request.Content.ReadAsMultipartAsync(provider);
// Show all the key-value pairs.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
if (key == "uploadType") UploadType = val;
if (key == "imageName") ImageName = val;
//Trace.WriteLine(string.Format("{0}: {1}", key, val));
}
}
foreach (MultipartFileData file in provider.FileData)
{
//Debug.WriteLine(file.Headers.ContentDisposition.FileName);
//Debug.WriteLine("Server file path: " + file.LocalFileName);
Image = Path.GetFileName(file.LocalFileName);
Dir = Path.GetDirectoryName(file.LocalFileName);
CurrentPath = file.LocalFileName;
}
if (UploadType == "update")
{
File.Delete(Dir + "\\" + Image);
File.Move(CurrentPath, Dir + "\\" + Image);
Imagen = ImageName;
}
return Request.CreateResponse(HttpStatusCode.OK, Image);
as some docs mention using await will cause the read process to be async, my problem is that I need to know when the file has been saved into the folder cause I want to delete it after if the UploadType form field is == to update, but it seems like when try this line
File.Delete(Dir + "\\" + Image);
the image is has not been saved yet and I got an error that the image don't exist, so my question is, how I can tell or be sure the image is ready in the dir? how can I tell the async process ends, thanks for any help on this!!
File.Exists is the method you should use.
Aside You should be using Path.Combine instead of building the path with concatenation.

Categories