Associate File Type and Icon

核能气质少年 提交于 2019-12-24 00:43:56

问题


Ok, I have looked all over and I am having a difficult time trying to figure out how to associate a custom file type with my C# application. I am using Visual Studio 2008 and am limited to .NET 2.0 due to company deployment.

Basically all I really want to do is be able to allow the user to double click my custom file type or drag and drop it on the app icon and it load the data, as well as display a custom icon on the file itself. I can open the file via a dialog box and everything works great.

Trying to read Micosoft's online documents is hard to understand and does not really give me all the details that I need. If anyone out there know's where I can find a good tutorial or can explain it I would appreciate it.

Thank you Patrick


回答1:


This CodeProject article has some source code demonstrating file association by code.




回答2:


I wrote this up in the newsgroups a few years ago. Skimming through it, I find that it's not the clearest I've ever written, but it's fairly complete. For what it's worth, I've reprinted it below:


First you need to create a subkey under HKEY_CLASSES_ROOT that will hold the commands that start your application. You should name this key something semi-descriptive. Your file extension[s] will be mapped to this key. For example, TXT files are mapped to a key named txtfile, by default. The benefit of using this setup is that if you have multiple extensions that your app can handle, you can map them all to this key. For example, many image editting apps create a subkey called something like "imagefile", and map .bmp, .jpg, .gif, etc. to that key. We'll call your key "JoeBlowFile". Next, you need to set the "default" value for your new JoeBlowFile key to a text string describing to the user just what type of file they have. This is what shows up in Windows Explorer under "Type". Again, to use the TXT file example, a good string here would be "Text File" or "Text Document". (It is the latter by default.) Your string might be "Joe Blow Data".

Now, under your new key, you can create another subkey, called "DefaultIcon". This, as its name suggests, sets the icon that is used with files of this type. You should create a custom icon that pictorially represents documents handled by your program. You can save this icon as an ICO file in your app's directory, but even better, you can include it as a resource in either your EXE or DLL. Either way, you'll then need to set the subkey's default value to a string representing the full path and filename of the ICO, EXE, or DLL. If there is more than one icon in the file (particularly likely if you include it as a resource in your EXE or DLL), you'll also need to add a comma, and either a zero-based positive index number representing which icon you'd like to use, or a negative resource ID, using the negative of whatever ID you've assigned your icon in your resource script. So yours could be, for example "C:\Program Files\JoeBlow\JoeBlow.exe, 2".

A note for C# developers on the above paragraph. Unfortunately, C# projects can't have resource scripts. Resources added to .NET applications by adding them to the project and designating them an "Embedded Resource" are included in a new .NET-specific format that's not compatible with previous methods. The only icon you can correctly embed in your application using C# on VS.NET is the application icon, accessible from the project properties. If you need additional icons—e.g. an icon to represent a document file handled by your app rather than to represent the app itself—you'll need to either include the ICO files themselves, compile a DLL with C++ with your icons embedded, or create and compile a resource script and include it in your project from the project properties.

Whether or not you choose to use the DefaultIcon key, you now need to create a subkey named "shell" under your JoeBlowFile key. Under the shell key, you'll create individual keys for each of the commands you'd like the user to be able to perform on your file type from the context menu (right-click menu). These items are called "verbs". For consistency, one of them should be "open"—this key, if it exists, will be the default (i.e. when a user double clicks on a file of your type, the open command will be performed). Instead, you can set the default value for the "shell" key equal to the verb you'd like to perform by default. You can optionally set the default value for each verb key to the text that you would like to appear in the context menu when a user right-clicks on a file of your type. An ampersand (&) can be used within this text to designate that the following character will be underlined, which means that the user can press the key corresponding to that character to select that command from the context menu. For instance, for the "open" key, you could put "Open with &Joe Blow's app" as the default value. That text then, with an underlined J, will appear in the context menu for files of that type, and a user can press the letter J to start Joe Blow's app.

The only thing you have to do, though, with the "open" (and subsequent) keys, is create another key as a subkey of that one called "command". The default value for the command key must be set to a string representing just that—the command required to perform that action. For instance, the default string in the command key under the "open" key might be ""C:\Program Files\JoeBlow\JoeBlow.exe" "%1"". Note the quotation marks around the path\filename for your app and around the %1. They are only neccessary around the path\filename of your app if there are any spaces in the path or filename, but they are absolutely a requirement around the %1 for 32-bit apps. The %1 is just like %1 in old MS-DOS batch (.bat) files. %1 is replaced with the first parameter on the command line, which in this case becomes the file name of the file your app is supposed to open. Because you do not know in advance if the path or filename containing the file you're supposed to open will contain spaces, you must put the quotes around %1.

Other required parameters for your app should also be included. For instance, the default value in the "command" key, under the "print" key might be ""C:\Program Files\JoeBlow\JoeBlow.exe" "%1" /print", or ""C:\Program Files\JoeBlow\JoeBlow.exe" /print "%1"". It's up to you how you want to process command line parameters in your app.

A note on replaceable parameters like "%1", mentioned above. Apparently, the "%1" parameter /may/ be replaced with the short filename to be opened. This isn't always the case, and I haven't figured out what criteria Windows uses to determine which it will pass—short or long. It may be that if the executable path listed in the registry is a long filename, Windows will replace %1 with the long filename to start, but if the executable path is a short filename, or can be interpreted as one, Windows will replace %1 with the short filename. If you want to be sure that you always get the long filename, use "%L" instead. You can use an uppercase L (as I've done) or a lowercase one, but I prefer to use uppercase because lowercase "l" looks way too much like the number "1".

What's more, if your program knows how to deal with Shell Item IDs, you can get that instead of the long filename with the "%i" parameter. Again, upper- or lowercase "i" are equally suitable, but I find uppercase "I" harder to distiguish from lowercase "l" and the number "1". If you don't know what a Shell Item ID is, it's okay. You'll probably never need to use one.

You're finally done with the JoeBlowFile key. The rest is relatively simple. You simply need to create (if it doesn't already exist) another subkey under HKEY_CLASSES_ROOT, and name it the same as the extension of your document type. To use the txtfile example, the name would be ".txt" (with the dot, but without the quotes). Yours (Joe Blow's) might be ".jbf" (for Joe Blow File). The default value for this key must now be set to the name of the first key your created, which in the example we've using is "JoeBlowFile".

That's it. You're done in the registry. Do remember that you'll have to make sure your app proccesses the command line in a manner consistent with the commands you set under the "shell" key. Window's won't open that file for you automatically when your app starts... you have to do it.

Graphically, it looks like this:

HKEY_CLASSES_ROOT 
| +--.jbf = JoeBlowFile 
| 
+--JoeBlowFile = Joe Blow Data 
     | 
     +--DefaultIcon = C:\Program Files\JoeBlow\JoeBlow.exe, 2 
     | 
     +--Shell 
          | 
          +--open = Open with &Joe Blow's App 
          |     | 
          |     +--command = "C:\Program Files\JoeBlow\JoeBlow.exe" "%1" 
          | 
          +--print 
               | 
               +--command = "C:\Program Files\JoeBlow\JoeBlow.exe" "%1" /print

If you don't already know how to modify the registry, look in MSDN for all the functions beginning with "Reg", including RegOpenKeyEx, RegCreateKeyEx, and RegSetValueEx. You can also do it the wimpy way by creating a ".reg" file and simply use ShellExecuteEx() to call "regedit.exe /s" on it. (The /s keeps Regedit from popping up a message box asking "Are you sure you want to add the information in [name of file.reg] to the registry?") The format of the a REG file is simple and straight forward. Here is an example REG file to add the "JoeBlow" example from above:

REGEDIT4 

[HKEY_CLASSES_ROOT\.jbf]
@="JoeBlowFile"

[HKEY_CLASSES_ROOT\JoeBlowFile]
@="Joe Blow Data"

[HKEY_CLASSES_ROOT\JoeBlowFile\DefaultIcon]
@="C:\\Program Files\\JoeBlow\\JoeBlow.exe, 2"

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell]

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\open]
@="Open with &Joe Blow's app"

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\open\command]
@="\"C:\\Program Files\\JoeBlow\\JoeBlow.exe\" \"%1\""

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\print]
@="&Print"

[HKEY_CLASSES_ROOT\JoeBlowFile\Shell\print\command]
@="\"C:\\Program Files\\JoeBlow\\JoeBlow.exe \"%1\" /print" 

Make sure that you include "REGEDIT4" as the first line of the file, or it won't work. Also make sure to press enter on the last line, or that line won't be read in. Altogether, adding your program to the registry this way is not as convenient as it sounds, because you'll have to modify your REG file if your app is installed anywhere except to C:\Program Files\JoeBlow.

The above instructions were aimed at a user programming directly to the Win32 API using C or C++. For C# on .NET, it's rather a bit easier. See the Registry class, or you can even do much of it graphically using a deployment project in VS.NET.


To add native-accessible resources to a .NET assembly, you will need a resource script. A resource script is a plain text file, like a code file. In fact, it is code; declarative code that is compiled by the resource compiler, rc.exe. A sample resource script follows:

#include <windows.h>

#define IDI_APP    100
#define IDI_FILE   200
#define ID_VERSION   1

IDI_APP  ICON "Resources\\Application.ico"
IDI_FILE ICON "Resources\\JowBlowFile.ico"

ID_VERSION VERSIONINFO
    FILEVERSION 1, 0, 19, 186     // change this to your version
    PRODUCTVERSION 1, 0, 19, 186  // change this to your version
    FILEOS VOS__WINDOWS32
    FILETYPE VFT_APP {
        BLOCK "StringFileInfo" {
            BLOCK "040904B0" { // 0x409 = U.S. English, 0x04B0 = dec 1200 = Unicode
                VALUE "CompanyName",      "Joe Blow, Inc.\0"
                VALUE "FileDescription",  "Joe Blow's App\0"
                VALUE "FileVersion",      "1.0.19.186\0" // change this to your version
                VALUE "InternalName",     "JoeBlow\0"
                VALUE "LegalCopyright",   "Copyright © 2008-2009 Joe Blow Incorporated\0"
                VALUE "OriginalFilename", "JoeBlow.exe\0"
                VALUE "ProductName",      "Joe Blow\0"
                VALUE "ProductVersion",   "1.0.19.189\0" // change this to your version
            }
        }
        BLOCK "VarFileInfo" {
            VALUE "Translation", 0x409 /*U.S. English*/, 1200 /*Unicode*/
        }
    }

The biggest drawback to doing this is that you have to add the version information manually to your resource script (unless you want to just forgo the version information altogether). In my applications, I add a custom build step that runs a program I wrote that updates the version information directly in the executable so that I don't have to manually update the version number in the resource script, but that program is not suitable for public release and is otherwise beyond the scope of this post.

Now you need to invoke the resource compiler to build this resource script into a binary resource file. Save this script as JoeBlow.rc, then start a Visual Studio Command Prompt. It's under Tools in the Visual Studio start menu folder. If you don't have Visual Studio installed, I believe you get rc.exe as part of the SDK. Microsoft also seems to be offering the latest version here.

Once at a VS cmd prompt (or otherwise have rc.exe in your path), just type:

rc JoeBlow.rc

Simple as that. The above resource script should compile without errors, given that the icons I've include exist. This will create a new file in the same directory called JoeBlow.res. Now, assuming you are using Visual Studio, all you have to do is edit the project properties to include this resource file.

These directions are for Visual Studio 2005 or 2008. I don't remember how to do this, or even if you can, in older versions, and I haven't tried out 2010, yet, but it's probably similar. Right-click on the project in Solution Explorer and select Properties (or select Properties from the Project menu on the main menu bar). On the Application tab, which is the first tab you should see, at the bottom is a Resources group box. Here, you have two options: "Icon and manifest", or "Resource File". Select the latter option. This will enable the text box where you can type (or browse to) your new resource file, JoeBlow.res.

Lastly, just build your project, and presto, you have embedded icons in native PE format accessible to the shell when browsing files associated to your app. Now if you set the value of HKEY_CLASSES_ROOT\JoeBlowFile\DefaultIcon to either C:\Program Files\JoeBlow\JoeBlow.exe,1 (using the zero-based index number), or C:\Program Files\JoeBlow\JoeBlow.exe,-200 (using the negative of the resource identifier, #defined above as IDI_FILE), your icon will show up in Explorer for .jbf files.

To get your new icons to show up immediately upon installation, you may need to refresh the shell's icon cache. I've found instructions on how to do that here. The basic gist is to change the shell icon size (at HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics) from its current value to a different one and back again, broadcasting a WM_SETTINGCHANGE message after each change.

Good luck. Let me know if you need anything else.




回答3:


Here is a discussion about how to use command-line utilities assoc and ftype to do this. You could invoke the command shell during a program deployment (or when the application is run) to do this.



来源:https://stackoverflow.com/questions/1903702/associate-file-type-and-icon

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!