开发者

Application File Association

开发者 https://www.devze.com 2023-03-04 03:15 出处:网络
Apologies for a long post.My question is what is the best method to allow my users to assign a file association to my app.I have included where I have gotten so far but I am not at all sure I am looki

Apologies for a long post. My question is what is the best method to allow my users to assign a file association to my app. I have included where I have gotten so far but I am not at all sure I am looking at it the right way.

My App uses a specific extension (.ad2). It is run by users using XP, Vista and Win7. I need to support them all. In Vista and Win 7 this needs Admin privileges of course. The location of my executable may differ depending on where the user install it. A good method I think would be to assign the association at ins开发者_开发知识库tallation. The problems here are that some of my users do not like automated installers and also there is a large installed base already. So I have elimiated that for now.

I want to give my users to control whether they associate or not so the process must be visible to them

The next I thought of was to embed some code in the application accessed via a menu. This works fine since the application knows where it is installed. However it requires to be Run As Admin (I understand that elevated privileges apply to the whole process). The user needs to elevate permissions before running to get around UAC however.

My last thought it to shell out to a new process from the Main App menu item, elevate the permissions on that process and allow it to do the file association. The shelled executable would be in the same folder as my main app so it would know where things like the main executable and icon are.

My preference is to shell out to a new process - am I right?

Thanks


The solution proposed by ScruffyDuck uses a home-grown approach to UAC that is non-standard and less functional than the standard facilities that are built-in to Windows and that developers are expected to use.

Applications that require administrator rights should be marked as such with a manifest:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel
          level="requireAdministrator"
          uiAccess="false"/>
        </requestedPrivileges>
       </security>
  </trustInfo>
</assembly>

Note: this is not a complete manifest, I have removed everything other than the requestedExecutionLevel setting.

Doing so means that an app will show a UAC elevation dialog when run.

Finally, none of this helps non-admin users. For this reason I would have opted for per-user file associations.


I am answering this with my findings because it may be useful to others. I claim no originality for this since all the code comes from others. I chose to create a separate executable to run the File Association Setting. I called that program from a menu item thus:

var proc = new ProcessStartInfo {
                UseShellExecute = true,
                WorkingDirectory = Environment.CurrentDirectory,
                FileName = Path.Combine(Application.StartupPath, "ADEFileAssociator.exe"),
                Verb = "runas"
            };

try {
      Process.Start(proc);
    }
catch {
       MessageBox.Show("Failed to start File Associator","Process Error",MessageBoxButtons.OK,MessageBoxIcon.Error);
       return;
       }

This approach was described in an answer here to another question and works fine. The File Associator appliclication double checks the operating system the user uses and will not start if the operating system is Vista or later and the app was not started with Administrator privileges. I did this since a user could run the external app directly. The code I used was this:

 var safeToRun = true;
 var os = Environment.OSVersion;
 if (os.Version.Major > 5) {//Got Vista or Win7
     if (!IsElevated) {
         var message = new StringBuilder();
         message.AppendLine("You are running Vista or Win7 and this program ");
         message.AppendLine("needs to run with Admin Privileges. When the ");
         message.AppendLine("program closes please right click on the executable");
         message.AppendLine("or icon and select 'Run As Administrator'.");
         message.AppendLine("");
         message.AppendLine("The Program will now close.");
         MessageBox.Show(message.ToString(), "Insufficient Privileges", MessageBoxButtons.OK, MessageBoxIcon.Error);
         safeToRun = false;
     }
 }

 if (safeToRun) {
     Application.EnableVisualStyles();
     Application.SetCompatibleTextRenderingDefault(false);
     Application.Run(new MainForm());
 }

IsElevated checks the current Priviledges:

public static bool IsElevated {
   get {
         return new WindowsPrincipal
            (WindowsIdentity.GetCurrent()).IsInRole
            (WindowsBuiltInRole.Administrator);
       }
}

Again this is not my code but from another answer.

Although I am sure someone will have a better way to do it. My external app is WinForm although it could be a command line.

EDIT Following David's comments and suggestions I know that this is not a good way to do things. However I hope that the overall question and answers (especially David's comments) will be instructive to others

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号