I have an application that works weirdly: the setup process copies the files to a temp folder, then checks a few things, and if everything is ok, moves the files to the final folder.
The problem is that the installer creates the shortcuts before the files are moved.
The result is that on the start menu (the one with the tiles), the icon is the "default sortcut" one.
I have tried to force the refresh of the system using this link (broadcast a WM_SETTINGCHANGE message) but it doesn't seem to work for the Windows 8 start menu.
Even rebooting the OS doesn't seem to refresh the icon, the only thing that works is to reinstall the soft on top of itself.
How can I force the icons refresh for the Win8 start menu ?
Thanks
First off, you don't tell us why your install process needs to work the way that it does. I agree that's weird, but I assume you have a good reason for doing it that way. If not, I suggest starting there and fixing the installer rather than putting band-aids on individual problems. You're bound to run into other problems later, and the root fix is bound to be much simpler and easier to maintain than a bunch of band-aids.
Anyway, if you must go down this path… The reason that broadcasting a WM_SETTINGCHANGE message doesn't work is because this doesn't have anything to do with icons. Those are managed separately by Explorer and don't get rebuilt unless you delete its icon cache. That, naturally, prompts it to rebuild it. It's a common troubleshooting technique for end users, but it's not something you want to do programmatically. Talk about an ugly hack. And altering the global state to solve a local problem.
Besides, if rebooting the OS doesn't work, you know it's not as simple as you make it sound in your question: a property in need of a refresh. The reason that reinstalling on top of the existing installation works is because when the shortcut gets created in the beginning, its target executable already exists in the expected place (put there by the previous installation) with a valid icon.
What I recommend doing is writing some code to change the icon of the existing shortcut. Make sure that you execute it after you've copied the executable file to its final destination. The method that allows you to do that is IShellLink::SetIconLocation, which takes two parameters: a path to the icon (this would be the path to your executable file), and the index of the icon (this would probably be 0 assuming that the icon you want is the first and only one contained in the executable).
Of course, in order to call SetIconLocation, you're going to have to obtain an object representing your shortcut that implements IShellLink. This is a COM interface, which I don't believe is wrapped anywhere by the .NET Framework. General information on creating shortcuts from C# is available in the answers to this question. More specifically, there's a link to this wrapper class that you can use to do most of the dirty work. I don't think it contains a method for setting/changing the icon, but that can be trivially added.
Alternatively, you can get at these same properties using the Windows Scripting Host (WSH) wrapper, WshShortcut. It has an IconLocation property that works much the same way except that it takes only a single string argument, with the index delimited from the path by a comma: myApp.exe, 0. It's not particularly well documented (best I can find), but to get an existing shortcut, you just use the CreateShortcut method and specify the path to the existing shortcut. For example:
public void SetShortcutIcon(string shortcutPath, string iconPath, int iconIndex)
{
// Note: no error checking is performed for the parameters!
// This is not production-ready code!
// If a shortcut does not exist at the specified path, you should
// create a new one instead.
// If iconPath does not specify a valid executable file, you should
// set a default icon or perhaps abort.
IWshRuntimeLibrary.WshShell wsh = new IWshRuntimeLibrary.WshShell();
IWshRuntimeLibrary.IWshShortcut shortcut = wsh.CreateShortcut(shortcutPath);
shortcut.IconLocation = String.Format("{0}, {1}", iconPath, iconIndex);
shortcut.Save();
}
Note that in order for the above code to compile, you will also need to add a reference to the Windows Script Host Object Model to your application. To do this, right-click on the "References" folder in the Solution Explorer, click the "COM" tab, and find "Windows Script Host Object Model" in the list.
I just tested this and it works; the effect is instant.
Related
I'm currently in the process of developing a small multi utilities tool in C# and one of the tools I am wanting to implement is a tool that will bind (File binder) one executable with another so that executing one executable will execute both of them in a way of merging the executables into one file.
Please take a look at this screenshot to understand more.
Figure 1:
Button 1 is the button which you click to select the first executable.
Button 2 is the button which you click to select the executable you want to bind with the first executable
button 3 is the button which you click to bind the executables and save the newly built executable to the desktop.
I need some advice on how I can do this, I am going to use codedom to build the file.
If by binding you mean chain-launching, then TheGeneral gave you the most simple suggestion in the comments, which to to generate a batch file with 2 lines of code (possibly more, for usability reasons):
Start "C:\...\...\executable1.exe"
Start "C:\...\...\executable2.exe"
Or better yet, use relative direcotries, which will start the executables that are in the working directory of the bat file:
Start "executable1.exe"
Start "executable2.exe"
Also, keep in mind that it might fail (if it needs admin rights at any point at all) without any errors on Windows 10, unless launched as administrator.
If you are looking for a method to modify an executable to launch a second executable, I don't believe you can tackle this project if you have no idea where to begin. If you want to modify executables to work on any system, you need to decompile the first file, modify it to launch the second one and recompile it, which is probably not difficult to do manually, but not easy to create an algorithm for.
Your 3rd option is to look into executable embedding (essentially creating a program, that contains your main and "bound" program, and when executed copies them out and launches them). After a quick google search, I've found that it is possible, but much like modification of executable, will require some effort to learn and implement.
I have the following strange behaviour in my Windows phone 8, C# App.
I am saving a Setting with:
private void SaveProperty<T>(T property, string propertyName)
{
if (IsolatedStorageSettings.ApplicationSettings.Contains(propertyName))
IsolatedStorageSettings.ApplicationSettings[propertyName] = property;
else
IsolatedStorageSettings.ApplicationSettings.Add(propertyName, property);
IsolatedStorageSettings.ApplicationSettings.Save();
}
When the app runs, I can read all settings I stored in IsolatedStorageSettings.ApplicationSettings.
But when I re-open my app (open it from the app list), the IsolatedStorageSettings.ApplicationSettings-Dictionary contains Zero (0) Keys and Values.
Am I missing something?
I used the ISETool.exe to take snapshots of the IsolatedStorage of my app (thanks to chepene).
I saw this behaviour: when I wrote the Settings (that means after the SaveProperty<T>() function finished), and the app is still running, I have the Settings saved in _ApplicationSettings. This agrees with my Observation that I can read from the IsolatedStorageSettings.ApplicationSettings when the app is running.
The _ApplicationSettings-file also exists when the is tombstoned or not running (when I can Access it by Holding the back-button of the phone and when the app is closed with the back-button).
But when the app is opened again (via the app list), the _ApplicationSettings-file is gone...
I also see that, when I'm writing a file into the IsolatedStorage with:
SharedStorageAccessManager.CopySharedFileAsync(
Windows.Storage.ApplicationData.Current.LocalFolder, fileName+"orig",
Windows.Storage.NameCollisionOption.ReplaceExisting, fileID);
and when I then don't read this file, it is gone when I open the app the next time.
By the way, to avoid confusion: I am not reinstalling the app each time I open it.
If you need more Information please ask.
Any help appreciated.
With AppSettings, I've seen something similar on WP7/7.5, but it happened only when my property-value's type was a class that was not known to the serializer.
Are you sure that there were no exceptions:
during Save
during App Exit (since the App may dump the settings at that point)
during the time that App loads the settings for the first time after launch?
Note that this doesn't necessarily must mean the app crashing. I mean, any exceptions, those internally silenced or user-handled too. Please check the VisualStudio's Output panel for "first chance exceptions" log. If any I/O or security or serialization exception shows up, then investigate there. If i remember well, there's even a whole set of isolated-storage exceptions that are easily interceptable from debug/exceptions menu.
However, the issues I had with unknown or nonserializable types does not explain at all why your extra non-appsettings files would evaporate.
Another thought: maybe some additional tool performs something like 'clean deploy' for you? I don't remember exactly, but I think that VisualStudio's deployment cycle was quite plain:
rebuild
remove/uninstall old app from device -- so probably purges isolatedstorage
install new app onto device
So, maybe that's the cause? Hm.. on afterthought and re-reading your question again, you've said about running the app from the applist, so that rather is not the case. Be sure to check firstchance exceptions then!
Thanks to quetzalcoatl I found the solution:
I am storing all my files in the root Folder of my app. At the start I am then reading all my files (via a DataContractSerializer) and casting it to my model. Since it happens sometimes that my files get corrupt, I delete every file which throws a SerialzationException. But as I read every file, and since _ApplicationSettings is not castable to my model, I am deleting _ApplicationSettings automatically.... So I learned that the ApplicationSettings are,just a file in the root folder, which I am allowed to read and delete. So the quintessence is to never write into the root Folder.
Can I allow a user to delete a file, under Windows, that is in use by my application?
In my scenario I have a "quick add" directory that is monitored by my application. When it sees a new image show up it creates a new slide to display in an automated slide show. I would also like to allow my users to delete (and/or rename) a file from my "quick add" directory, and remove it from the slide show.
Is there a way I can flag the file that notifies Windows that I'm okay for it to remove the file while my application is using it?
Is there a way I can flag the file that notifies Windows that I'm okay for it to remove the file while my application is using it?
Yes. In Win32 this is dwShareMode passed to CreateFile(). This is a bitfield of what you would like to permit another process to do. The bit you are looking for is FILE_SHARE_DELETE which allows a delete or a rename while open. However, for the most polite behavior I would recommend including all 3, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE.[1]
Since you're asking about C# and not Win32, in the .NET world these are included in the FileShare enumeration which you can pass when opening a file, eg. in File.Open.
Note that these flags don't let you allow a rename of a file's parent directory while it is opened by name. That will fail regardless of sharing due to limitations in the kernel (technically in ntfs.sys IIRC).
Footnote
1: Editorial comment: It is a shame that passing 0 (which many people do without thinking) happens to be the least permissive option, or that more people writing code on Windows don't realize what this parameter does and pass these three flags.
If you call a Delete() or Rename() method onto the Control that is using the file, you can remove it from the PictureBox before it deletes or renames the file.
There shouldn't be much of an issue with doing multiples. With a Checkbox on the Control, you just check each Control to see if that property is true, then call the appropriate method.
This question already has answers here:
Why does rename a loaded .net assembly work?
(3 answers)
Closed 5 years ago.
We are trying to push updates to multiple servers at once and my manager has found that it is possible to rename running .exe file. Using that knowledge he wants to rename a running exe and copy over a new version of said exe such that anyone running their in memory copy of foo.exe are fine and anybody who opens a shortcut pointing to foo.exe will get a new copy with updates applied.
I guess I need to clarify, He doesn't expect the old copy to magically update, he just expects them to keep running the old copy until they open the exe again, in which case it will then open the new one that has the name of the old one.
It sometimes throws an exception that the file is in use on his program but if he tries renaming it in a loop it will eventually succeed. On my machine I have yet to be able to get it to work even in a loop.
My first and main question is this: Is it ever acceptable to do this. Should renaming a running executable ever be a valid scenario?
Secondly, if it is a valid scenario then how could one reliably do this? Our current thoughts are try a bunch of times using File.Move (C#) to do a rename and if it doesn't work then write out to an error log so it can be handled manually.
An airplane mechanic and a surgeon meet in a bar. The mechanic says "you know, we have basically the same job. We take broken stuff out and put new, better parts in." The surgeon says "yeah, but you don't have to keep the plane flying as you're making the repairs!"
Trying to update an application by moving files while the application is running seems about as dangerous as trying to fix an airplane in flight. Possible? Sure. Greatly increased risk of catestrophic crash? Yep.
If the application you are updating is a managed application, consider using ClickOnce Deployment. That way, the next time someone runs the application, if there is a new version available it will be copied down and installed automatically. That's much more safe and pleasant than trying to mess with an application while its still running.
No, this is not acceptable. Do not do this. This is not a valid deployment mechanism. This should have been yours or his first clue:
It sometimes throws an exception that the file is in use on his program but if he tries renaming it in a loop it will eventually succeed.
And it won't work, anyway. His theory is quite wrong:
Using that knowledge he wants to rename a running exe and copy over a new version of said exe such that anyone running their in memory copy of foo.exe are fine and anybody who opens a shortcut pointing to foo.exe will get a new copy with updates applied.
Specifically, the copy in memory will not be automatically replaced with the new executable just because it has the same name. The reason that you're allowed to rename the executable in the first place is because the operating system is not using the file name to find the application. The original executable will still be loaded, and it will remain loaded until you explicitly unload it and load the new, modified executable.
Notice how even modern web browsers like Chrome and Firefox with their super fancy automatic, in the background, no one ever notices that they exist, updaters still have to close and relaunch the application in order to apply the updates.
Don't worry about shooting the messenger here. It's more likely that your customers and your tech support department will shoot you first.
See number 1.
In our organization, we solved the problem of Updates by having two release folders say EXE_A and EXE_B. We also have a release folder called EXE which only has links ALL of which points to either to EXE_A or EXE_B from which the user runs the applications.
When we publish a new version of the program, we publish it to the folder that is not referenced in the links and then update the links (EXE). In this way, you do not get into exceptions that users are holding the application / assemblies. Also if a user wants to run the updated version, all he need to do is close / re-execute the link in EXE folder.
If you use Windows Vista/Server2k8 or newer you could use mklink to create a symbolic link to the folder containing your application and start the application out of the "symblic linked folder" and then at the update create a new folder, e.g. "AppV2" and change the SymLink to that folder, so the next time the user restarts the application he starts it out of the new folder without noticing.
Renaming open files is ALWAYS a bad choice!
But in general I would think of a better deployment strategy anyway, because if you need to use such "hacks" it is always a messy situation. I don't know your application, but maybee ClickOnce would be a point to start, because you can configure it to check for updates on every start...
The problem is easy: I've a lot of desktop shortcuts which points to a lot of file, BUT I also have a lot of shortcuts which points to directories pointed by those shortcuts. I want to remove this redundance by simply adding another rightclick menu options for all shortcuts (.lnk files) that allows you to open explorer.exe to the directory containing the file pointed.
While I discovered how to retrive the target of a shortcut and it's working, I found a suggestion on how adding a menu item to rightclick context menu, but it's not working (I put a key under HKCR*\shellext\ContextMenuHandlers called Test and set the base value to "cmd.exe"
But it doesn't work, obviusly
any suggestion?
Update 1:
How to add an icon to that menu item?What size should the icon file have? 16x16 or 32x32?
thanks in advance
Go into HKCR\lnkfile
Create a new key called "shell", and below that create another key called whatever you want the display text to be for your context menu handler, I called mine "COMMAND".
Next, create yet another key below that called specifically "command" and make the (Default) value be "cmd.exe", which will be the path to your custom command. Remember to wrap it in quotes if you're going to be pointing to an exe that has spaces.
So for this example, the final key ends up being:
HKCR\lnkfile\shell\COMMAND\command\
Add the (Default) value mentioned above and your test will be working fine.
Additionally, you can use "%1" to specify the full path to the .lnk file being accessed by the context menu, again remember to wrap it in quotes since you never know if it'll be a file that has spaces in it's full path.