Add Images to windows form so they work after publish - c#

I am currently setting my images in my windows form like this:
pictureBox1.Image = Image.FromFile("C:\\Users\\User\\Documents\\Visual Studio 2013\\Projects\\WindowsFormsApplication1\\WindowsFormsApplication1\\Krum\\11.jpg");
But this will not work after I publish the product and load it from another computer at another location.
How do I add images to my project so that they will work after I publish and send it to another computer? What path do I use and where do I need to add them?
UPDATE:
Trying to find the path to my file after adding it to properties is not working very well. In my prperties the file looks like this:
internal static System.Drawing.Bitmap one {
get {
object obj = ResourceManager.GetObject("one", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
And then I try to use it like this:
System.Reflection.Assembly thisExe;
thisExe = System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream file =
thisExe.GetManifestResourceStream("WindowsFormsApplication1.Properties.Resources.one");
this.pictureBox1.Image = Image.FromStream(file);

Add the image file to the project, and set the Build Action property to Embedded Resource in Solution Explorer and then use something like:
System.Reflection.Assembly thisExe;
thisExe = System.Reflection.Assembly.GetExecutingAssembly();
System.IO.Stream file =
thisExe.GetManifestResourceStream("AssemblyName.ImageFile.jpg");
this.pictureBox1.Image = Image.FromStream(file);
reference: http://msdn.microsoft.com/en-us/library/aa287676(v=vs.71).aspx

If you do not want to embed the images in the assembly file, you could always add them to your solution, set the property "Copy to Output Directory" to "Always", then use the following code to acces relative paths:
var directory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var filename = Path.Combine(directory, "Images", "Image1.png");
Additionally, if you are using a setup project, also include the folder/files to install along with the assembly.

Related

Hide Json file containing GOOGLE_APPLICATION_CREDENTIALS when building executable file in Visualstudio [SOLVED]

currently I am developing a tool that interacts with a Firebase Firestore database. When I want to make the C# Forms Application an executable file I get the .exe but also the json file which contains the Google App Credentials. However, I want to forward the tool so that you can't see the json file or read the contents of the file, so you only need the .exe file. Is there a way to achieve this? For example, define the app credentials in a C# script so that it compiles to the .exe file? If so how?
My current implementation looks like this:
string path = AppDomain.CurrentDomain.BaseDirectory + #"cloudfire.json";
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", path);
The cloudfire.json file is directly contained in the namespace "LUX".
I also tried making the cloudfire.json file a resource, since i read this post but then the problem is, that i can't set the path of the .json, if i try it like that:
var assembly = Assembly.GetExecutingAssembly();
string resourceName = assembly.GetManifestResourceNames()
.Single(str => str.EndsWith("cloudfire.json"));
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", resourceName);
I get the error: System.InvalidOperationException: "Sequence contains no matching element"
Is there maybe a way to set the "GOOGLE_APPLICATION_CREDENTIALS" to the embedded cloudfire.json ressource file?
EDIT:
I solved the problem by adding the "cloudfire.json" file to Resources.resx and changed the modifier to public. Like mentioned here.
Since you can only set the GOOGLE_APPLICATION_CREDENTIALS by using this code:
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", "path to file");
I solved it by creating a temporary file:
byte[] resourceBytes = Properties.Resources.cloudfire;
// Write the resource to a temporary file
string tempPath = Path.GetTempFileName();
File.WriteAllBytes(tempPath, resourceBytes);
// Set the GOOGLE_APPLICATION_CREDENTIALS environment variable
Environment.SetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS", tempPath);
Add you file as embedded resource with name. And try to read by following code:
var resources = new ResourceManager("<namespace>", Assembly.GetExecutingAssembly());
var obj = resources.GetObject(<embedded_resource_key>);
or
var str = resources.GetString(<embedded_resource_key>)

Referencing a file inside of a Project without using its absolute path?

I'm using StreamReader to dynamically replace content in an HTML template. The HTML file has been imported into my project.
Right now I'm having to referencing the HTML file a static location on my dev box because I'm not able to find the right syntax to reference it once it's been imported into my VS project.
How do I refer to the file without using an absolute path?
Current implementation for reference:
StreamReader reader = new StreamReader(#"C:\Users\n00b\Desktop\EmailTemplate.html");
{
body = reader.ReadToEnd();
}
One common thing I've seen is to put the file's location in a configuration file. This lets you change the file location at will without having to recompile.
You can add it as an embedded resource and extract it this way.
using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("<namespace>.Resources.EmailTemplate.html"))
per your comment
using (System.IO.StreamReader sr = new StreamReader(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("<namespace>.Resources.EmailTemplate.html"))
{
body = sr.ReadToEnd();
}
There are 2 main ways to do this, In a desktop application, the current directory of the .exe is set to the directory where it is launched from by default. Unless that is changed by launching the .exe by a shortcut with special settings, or by another process using a special feature, it should be the default value. If that is the case, you can just use a relative path. For example, if you have a file named "data.txt" in a folder called "things" inside a folder called "stuff" in the same directory as your app, you can just us the relative path "stuff/things/data.txt" directly and Windows will work it out for you.
If you need to be absolutely sure you are targeting that file, even if the app launches with a modified current directory, you can get the .exe's path, and combine it with a relative path using System.IO.Path.Combine.
var appPath = Assembly.GetEntryAssembly().Location;
var filePath = "stuff/things/data.txt"
var fullPath = System.IO.Path.Combine(appPath, filePath)
If, for some reason, you need to up "up" from the application's directory, you can use ".." to represent that parent folder of a directory. So "../data.txt" would look in the folder that contains the current directory for a file named "data.txt".
You could also change the app's current directory when it starts to be the directory of the .exe, and then reference everything via relative path, as in the first example.
var appPath = Assembly.GetEntryAssembly().Location;
System.IO.Directory.SetCurrentDirectory(appPath);
I found two solutions to this:
If you don't care if the external file is visible in the build directory/installdir of your app:
StreamReader reader = new StreamReader(#"../../EmailTemplate.html");
{
body = reader.ReadToEnd();
}
If you want your external file to be invisible once compiled:
var embeddedResource = "<namespace>.EmailTemplate.html";
using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(embeddedResource))
{
StreamReader sr = new StreamReader(stream);
body = sr.ReadToEnd();
}
Note the 2nd solution requires adding your external file and changing the build action to "Embedded Resource" on the properties menu of that file within Visual Studio.

getting root of wpf app as a string

Is there another way to get the root of a wpf application as a string?
Now I'm still using
string path = AppDomain.CurrentDomain.BaseDirectory.Substring(0, (AppDomain.CurrentDomain.BaseDirectory.Length - 10));
This gives me the root as a string, but I assume this is not the right way to do it.
I also tried
string txt = System.AppDomain.CurrentDomain.BaseDirectory.ToString();
but this sends me to root/bin/debug.
I only need the root as a string
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
Another way is:
Environment.CurrentDirectory
if it was not changed.
You can find the file path of the root folder of the startup project in a WPF App like this:
string applicationDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
string rootPath = Directory.GetParent(applicationDirectory).Parent.FullName;
Or to complete your example by getting the file path of the parent folder of the parent folder, you can do this:
string rootPath = Directory.GetParent(txt).Parent.FullName;
UPDATE >>>
In order to access your project Images folder, you can do this:
Path.Combine(Directory.GetParent(applicationDirectory).Parent.FullName, "Images");
You should put the images in a folder of your Visual Studio project called "Images" and set their Build Action to Resource (as shown here).
If you then get a relative image path from your DB, you would create a Pack URI and load a BitmapImage like this:
var imagePath = "Images/SomeImage.jpg"; // actually from DB
var uri = new Uri("pack://application:,,,/" + imagePath);
var bitmap = new BitmapImage(uri);

Path is wrong (FileNotFoundException)

I have this chunk of code:
private void button4_MouseEnter(object sender, MouseEventArgs e)
{
System.Media.SoundPlayer player = new System.Media.SoundPlayer(#"Resources/navigation.wav");
player.Play();
}
And I get FileNotFoundException, but navigation.wav is in Project/Resources. Plese help!!!
This looks for the file from your Bin\Debug Folder
You have couple of options:
Right click the file and pick Properties. Select for BuildAction = Content.
You will find the file under Bin\Debug\Resource\Sound.wav
Right click the file and pick Properties. Select for BuildAction = Embedded Resource.
var assembly = Assembly.GetExecutingAssembly();
var resourceName = "NamespaceName.FolderName.Sound.wav";
using (Stream stream = assembly.GetManifestResourceStream(resourceName))
{
var wave = new WaveFileReader(stream);
Console.WriteLine(wave.TotalTime);
}
The path is determined relatively from the executable, so in this case probably Bin\Debug.
Try to add the resource in your application as Content (it copies the file to Bin\Debug). That should work.
That path is relative to the directory in which the application is currently running. If you hit F5 in Visual Studio this is most probably bin/Debug, so the file should be there.
Consider embedding this resource, or setting Copy to output directory property to "copy always".
To start with, you need a backslash: #"Resources\navigation.wav"
If this doesn't help, then most likely you are running your application from a different directory than you think. Are you running in debug mode from VS? Is your file in Project\bin\Debug\Resources then?

Get Files In Project Folder

I have an Images folder in my visual studio project.
How can I reference the images within this folder so I can use the .exe file on other computers?
Ultimately I am trying to do the following (obviously replacing "Images/image1.jpg" with imageFile).
foreach (string imageFile in imageFolder)
{
ImageSource imageSource = new BitmapImage(new Uri("Images/image1.jpg", UriKind.Relative));
}
Using something like:
Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName
doesn't work because the .exe could be running in any location.
If you don't need to add or remove such images during the installation of the application on the user's computer, add the images to the resources by dragging them to the Resources tab in the project properties and reference them using Properties.Resources within your code.
If you're using copying the image folder to the output of your application and taking the folder with you to the new computers you could use
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().CodeBase)
If you don't have lots of large images, why not include them as embedded resources. http://support.microsoft.com/kb/319292
Keep images (and other resources) together with exe-file (either in the same folder, which is simplest, or use directory structure).
To example:
\Bin
my.exe
my.pdb
\Help
my.html
\Resources
1.jpg
2.jpg
Then you can so something like
private static string PathRoot { get { return Path.GetDirectoryName(Path.GetDirectoryName(Application.ExecutablePath)); } }
public static string PathResources { get { return Path.Combine(PathRoot, "Resources"); } }

Categories

Resources