WPF: Image Path doesn't work after publishing - wpf

I have a trayicon in my WPF App. When I was debugging in Visual Studio, it works well:
System.Windows.Forms.NotifyIcon ni = new System.Windows.Forms.NotifyIcon();
ni.Icon = new Icon("../../logo,ico");
But after I published it, the App threw an exception saying it could find the path of the image of the trayicon. I've search a lot resources on online, I saw many solutions use pack, but it seems pack only accept Uri variable and the path for trayicon must be string. I also tried to create a folder called Resource under the project solution and put the image file into it. This was the same: worked while debugging but would not work after publishing..
So based on #WPF Germany's suggestion, I solved the path issue after publishing the App by Clickonce. However, if I copy a App shortcut to system startup folder, it would find the ico in C:\WINDOWS\system32, which is not easy to workaround since systems32 usually requires admin right to access. Any idea for that?

Did you check, that your logo.ico file is copied to output path?
In VS you have multiple options to provide your Resource files.
First option:
Select your logo.ico file in solution explorer and choose None as Build Action and Copy always at Copy to Output Directory (at file properties).
After compiling you will find the file in a subdirectory of our OutputPath.
use (if logo.ico is placed in your projects root):
ni.Icon = new Icon("logo.ico");
other option:
Use Resource as Build Action and build your Icon using a Stream created from Resources.logo...

Related

Packaged WPF app returns wrong AppData path when used as argument for a new process

I have a WPF .NET Core 3.1 app packaged as an MSIX app. The app downloads some assets from S3 to the AppData folder and at some point, it starts another process (another app) with one of the arguments being the path to one of the downloaded assets (a Settings.xml file).
I'm facing two problems:
The app sometimes downloads the assets to the "real" AppData path (C:\Users\my_user\AppData\Local\some_created_folder), sometimes to the virtualized path (C:\Users\my_user\AppData\Local\Packages\package_id\LocalCache\Local\some_created_folder). I noticed the latter only recently in 3 different releases (3 consecutive versions): 1st used "real", 2nd used virtualized, 3rd used "real" once again. I'm pretty sure there was no code change that could cause this.
I'm composing the download paths using Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData). When the assets are being downloaded to the virtualized path, the 2nd app is not starting correctly, because the settings file path set as an argument when starting the process is pointing to the "real" path (always!). No exceptions or errors are thrown!
var appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
var settingsFilePath = Path.Combine(appData, "Settings", "Settings.xml");
...
var settingsFile = new FileInfo(settingsFilePath);
if (settingsFile.Exists)
{
var arguments = $"-l \"{settingsFile.FullName}\"";
var fileInfo = new FileInfo(_options.ExePath);
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = fileInfo.FullName,
WorkingDirectory = fileInfo.DirectoryName ?? string.Empty,
Arguments = arguments
}
};
if (process.Start())
{
process.WaitForInputIdle();
}
_logger.LogDebug("Started {name} {arguments}", fileInfo.FullName, arguments);
}
else
{
throw new FileNotFoundException($"Settings file not found at path '{settingsFile.FullName}'!", Path.GetFileName(settingsFile.Name));
}
I read this, but I don't understand why the app is acting this unpredictable. Or am I missing something? The package manifest file has the EntryPoint="Windows.FullTrustApplication". I'm also aware that UWP Desktop Bridge virtualizes some File System paths, but I'm expecting it to be predictable.
Questions
How can I make sure that my downloaded assets are always on the same path, either the "real" one or the virtualized one?
How can I set the argument for the 2nd app to always point to where the file really exists ("real" vs virtualized)?
I don't have an anwer yet, but I need more details from you to further investigate this:
Are you sure the files under the "real" appdata folder are not created accidentally by you when debugging the app from VS?
From what I know, packaged apps work with the plain, real AppData resource and path when they open a folder or file already present in that location. If the Appdata folder/files are created from scratch then it should use the virtualized location.
This behavior is useful when migrating from MSI to MSIX, until the user chooses to uninstall the MSI version, the MSI and MSIX variant can be used in parallel both having access to the same AppData files.
Then again, if this is not the first version of your app, and you have previously deployed it as an MSI to your users, you will not be able to know for sure which AppData folder you are working with when running from inside the container.
C:\Users\my_user\AppData\Local\some_created_folder
However, while researching this I found that you can also use Windows.Storage.ApplicationData.Current.LocalFolder.Path to write your appdata. Maybe this would work?
Windows.Storage.ApplicationData.Current.LocalFolder.Path changes the path during normal debug and a test
The second app, is that an EXE from the same MSIX package or another separate application (deployed with its own MSI/MSIX) from the machine? I might be wrong, but if remember correctly the virtualized AppData folder is accessible only inside your app container, so other apps from the machine can't access those files.
If that is the case, you could try saving the data in the CommonApplicationData folder, if this isn't user-specific data.
Related question:
How to allow for editable .Net generated config files with MSIX?
I read this, but I don't understand why the app is acting this
unpredictable. Or am I missing something? The package manifest file
has the EntryPoint="Windows.FullTrustApplication". I'm also aware that
UWP Desktop Bridge virtualizes some File System paths, but I'm
expecting it to be predictable.
From that link you provided, the details for the reasons why it appears "unpredictable" (note: the behaviour is slightly different before and after Windows 10 1903):
In response to a file open command, the OS will open the file from the
per-user, per-package location first. If this location doesn't exist,
the OS will attempt to open the file from the real AppData location.
If the file is opened from the real AppData location, no
virtualization for that file occurs.
And
All newly created files and folders in the user's AppData folder
(e.g., C:\Users\user_name\AppData) are written to a private per-user,
per-app location but merged at runtime to appear in the real AppData
location. ...
Modifications to existing files under the user's AppData folder is
allowed to provide a higher degree of compatibility and interactivity
between applications and the OS. ...
State separation also allows packaged desktop applications to pick up
where a non-packaged version of the same application left off.
The affected directories are:
Local
Local\Microsoft
Roaming
Roaming\Microsoft
Roaming\Microsoft\Windows\Start Menu\Programs
So, to answer you questions:
How can I make sure that my downloaded assets are always on the same path, either the "real" one or the virtualized one?
To always use the virtualized directories, look at the Windows.Storage.ApplicationData API. The function Local[Cache]Folder will always return the virtualized path.
Failing that, you must make sure that you (or a user) have never written to the non-virtualized AppData locations (e.g. C:\Users\user_name\AppData\MyCompany) as that will always be used in preference to the virtualized location (e.g. C:\Users\user_name\AppData\Local\Packages\MyCompany.MyApp_PublisherId\LocalCache\). That way, you will only ever read and write to the virtualized location.
How can I set the argument for the 2nd app to always point to where the file really exists ("real" vs virtualized)?
The virtualized path to the file is the "real" file.
However, files in this location are only visible to the packaged app itself (see https://learn.microsoft.com/en-us/windows/msix/desktop/flexible-virtualization):
Files in the virtualized location are visible only to the app.
One final thing to note. When a user uninstalls an MSIX package, it will delete all of the virtualized AppData that your application wrote.

Changing Directory of STM32CubeIDE Projects

When I create a new STM32CubeIDE project, it default saves it to my /Documents directory. This isn't too bad except I like to have a folder for each application so that it isn't just a bunch of files. I tried creating a folder called "STM32CubeIDE" to save new projects to, put it gives me an error: "overlaps the location of another project".
I've done some googling and found that this issue also exists in Eclipse (which makes sense) but couldn't solve my problem from those solutions.
I was also wondering if there is a way to move all of my existing projects to this newly created folder? Last time I tried, the IDE flipped out on me and couldn't find my stuff.
First of all, do not call your folder "STM32CubeIDE" if this already exists. Use a different name, because this is normally used by default and it may cause issues (probably the reason why you are getting that error).
When you install or update STM32CubeIDE it gives you the option to choose where you want your default folder to be. For example, my default folder is
C:\Users\%USERPROFILE%\STM32CubeIDE\workspace_1.6.0\
Now if you want to use different folders for different projects, there are two options:
You can Export your project (application) to a desired folder and then Import it using the File tab. This is a good method if you want to make backups, or just want to make sure that all relevant files are transferred correctly to avoid "missing file" issues.
The other method (my favourite) is to simply copy you project folders and paste them to a different folder, wherever you want to put them. Then you simply open STM32CubeIDE, go to File > Open Projects from File System... and chose your project. You might get a pop-up about software compatibility issues (if you made an update), etc. but this should open up your project and show it in the Project Explorer.

My installed WPF app is crashing while trying to create a file

I have a problem with my WPF application (a simple clicker game). I've just made a deployment/created a setup project using Microsoft Visual Studio Installer Projects extension for Visual Studio. Everything seemed to work fine, setup works good (tested on other computer) and furthermore the installed application almost works correctly. The only exception is a button calling function which is creating a new txt (something like a draft of a "save" file) file in a folder where the application is installed. Clicking this button cause instant crash of the whole application. Nothing else happens, no error message, the app just turns off.
I assume that the problem lies in access rights to the folder/administrator rights.
I've added txt file with the same name in the application folder using "File System" window in setup project, deployed and installed again. Even when the file exists the problem happend again (probably because of access rights when trying to override file content).
It's may be important that everything worked while running app through VS, also using .exe works fine on any computer. The problem is only with application installed using setup.
I'm not sure where the problem is so it's hard to show some code, to be honest i'm not even sure if it's a problem with code, maybe it can be solved with setting some setup project properties?
I would like to store some data locally between two sessions, i've choosed txt file because it's light and simple even if it's not the most elegant way.
I expect that installed application will be able to create and override txt file in it's folder.
P.S. if you need any code, screenshots or information about my setup please let me know in comments section, I will provide what's necessary
At the moment you install your program you're having administrator-rights. So the folder where your application is, also was created with administrator-rigths.
If you want to store data to this folder, you'll have to run your application as administrator. (not the best idea)
Otherwise you can change your code to write your file at runtime to a different location where you don't need administrator-rights.
For example:
string path = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
will give you: "C:\Users\MyUserName\AppData\Local"
string path = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
will give you: "C:\Users\MyUserName\AppData\Roaming"
string path = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
will give you: "C:\Users\MyUserName\Documents"
And some error-handling around the saving of the file would be very nice and helpful ;)
Thank you everyone for solution and knowledge, the problem was as I assumed (access to the path denied).
I was using this code to create a path:
Directory.GetCurrentDirectory() + "\\SyntyhCitySave.txt";
Creating a file in a special directory instead of application folder works, that's the solution for my problem:
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + "\\SyntyhCitySave.txt";
Tomtom answer marked as accepted.

Extremely simple app and a text file, best way to distribute on Windows Store?

I have an extremely simple application I'd like to distribute on the Windows Store. This is the first I've looked at Store.
The entire project consists of the exe and readme.txt. The app has a button that opens a second window and displays the contents of the readme.
The exe will be packaged using Desktop App Converter (DAP). Is there a way I can add the text file to the package as part of the DAP process or post-process?
I know I can put the file inside the exe as a resource, but I'd like to avoid doing that simply so the user can open it in their own text editor as well.
Is there a way I can add the text file to the package as part of the DAP process or post-process?
You could firstly use DAC tool to convert your WPF application. Then you could modify the packaged app by adding the text file into visual assets folder:
Then you need to manually generate a new Package Resource Index file and repackage your app using MakeAppx tool.
You could open your command tool and Change directory to the package's root folder, and then create a priconfig.xml file:
makepri createconfig /cf priconfig.xml /dq en-US
Create the resources.pri file(s) by using the command
makepri new /pr <PHYSICAL_PATH_TO_FOLDER> /cf <PHYSICAL_PATH_TO_FOLDER>\priconfig.xml
For example: makepri new /pr c:\MYAPP /cf c:\MYAPP\priconfig.xml
Finally, you need to generate a new package:
makeappx pack -d "C:\VLCUWP\VLCUWPApp\VLCUWPApp\PackageFiles" -p "C:\VLCUWP\VLCUWPApp\VLCUWPApp\VLCUWPApp.appx".
For more details, please refer to Create an app package with the MakeAppx.exe tool.
With Visual Studio 2017 Update 4, this has become much easier now. You don't have to use the Desktop App Converter for projects like this anymore, you can do the packaging directly and easily in VS with the new Packaging Project type. You can just add that to your WPF source project and it will take care of packing the EXE and the text file and whatever else you want to package into the .appx package.
Here is a blog post explaining the details:
https://blogs.windows.com/buildingapps/2017/10/18/visual-studio-2017-update-4-makes-easy-modernize-desktop-application-make-store-ready/

Why do I get a "Metafile not found" error when trying to compile a WPF application?

I had to rebuild a project in my application.
I created a new project, created each file, and copied the contents of each file into the new project one at a time making all the necessary changes.
Now when I try to compile the project, it gives me three errors:
The metafile c:\projects\project1\CustomerModule\bin\Debug\CustomerModule.dll could not be found.
Application Definition Element could not be given by the library project file.
The project file has invalid properties.
Clicking any of these does nothing.
What are these errors telling me? What do I need to change to get my application running again?
New info: If I do a "rebuild" on just the project, I only get the second two errors, so these seem to be the original issue, but what is the library project file and what properties are invalid?
I found the answer on this forum question.
Basically the thing I did wrong was copy images from a directory in one module to a directory in another module within the Solution Explorer. Don't do this. Instead, copy them from the Windows Explorer into the Solution Explorer, then everything works fine.
Click add a reference and browse for the dll file you want to use.
You may have to rebuild the dll for it to work.

Resources