zoukankan      html  css  js  c++  java
  • 文件关联(C#和Inno脚本实现)

      最近在做一个APK安装器,需要:可双击打开,或者右键点打开可自动开启所做的APK安装器。其实文件关联就是一些注册表的添加,修改和删除,以前没做过太多注册表操作,在网上搜了很多,结果发现都有一些问题,最后从乔尔(新浪技术博客)那里看到一些操作,然后稍作修改,实现文件关联,图标关联。

      因为我之前是关联的.APK文件,就一关联.APK文件说事儿了。

      文件关联操作主要的几个地方:

    1.删除操作:删除根目录CurrentUser下面的Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.apk下面的所有子节点,这一点很重要,也很霸道,最初我没操作这一步,结果无论我怎么关联,都是不成功的,双击.apk文件的时候,它启动的始终不是自己做的apk安装器。霸道是因为:之前电脑里面.apk可能已经和某个EXE关联,我们删掉这里,就断了他们的直接关联,这是让apk文件和我们的安装器直接关联的第一步。

    2.添加操作:在根目录ClassesRoot下添加一个节点,如CN.APKInstaller,第二步:添加子节点defaultIcon,这个是默认的图标,然后指定本地一个ico文件路径,这样凡是电脑上面的apk文件都会变成你指定那张图片;第三步:在CN.APKInstaller下添加子节点shell,然后再在shell下添加两个子节点open和play,open节点值设为"打开APK",play节点设为"用APKInstaller打开"。这样你在一个apk文件上点击右键就会看到你设置的东西了。

     3.继续添加操作:上一步操作,分别在open和play节点下添加同样的command节点,然后设定command值是你本地APKInstaller的执行文件路径加上一个   " %1”,如"C:\Program Files\APKInstaller.exe" "%1",后面的"%1"是为了实现双击时可以打开EXE。

    4.修改操作:修改在根目录ClassesRoot下面的.apk节点的值,设置为CN.APKInstaller,完成。

    主要代码如下:

      首先是一个系统API,可以使你的修改不用重启电脑就可以生效:

    int SHCNE_ASSOCCHANGED = 0x08000000;
    int SHCNF_IDLIST = 0x0000;        
    
    [DllImport("shell32.dll")]
    static extern void SHChangeNotify(HChangeNotifyEventID wEventId,
                                               HChangeNotifyFlags uFlags,
                                               IntPtr dwItem1,
                                               IntPtr dwItem2);
    
    接下来是一个封装好的方法,直接调用就可以了:
    View Code
     public void SetValue(string exeName, string nodeName, string iconPath)
    {
                RegistryKey key = Registry.CurrentUser.OpenSubKey(@"Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts", true);
                if (key.OpenSubKey(".apk") != null)
                {
                    key.DeleteSubKeyTree(".apk");
                    key.CreateSubKey(".apk");
                }
                if (Registry.ClassesRoot.OpenSubKey(nodeName) != null)
                {
                    Registry.ClassesRoot.DeleteSubKeyTree(nodeName);
                }
                if (Registry.ClassesRoot.OpenSubKey(nodeName) == null)
                {
                    RegistryKey progId = Registry.ClassesRoot.CreateSubKey(nodeName);
                    progId.SetValue("", "APK Instarller");
                    RegistryKey defaultIcon = progId.CreateSubKey("DefaultIcon");
                    defaultIcon.SetValue("", iconPath);
    
                    RegistryKey shell = progId.CreateSubKey("shell");
    
                    RegistryKey open = shell.CreateSubKey("open");
                    open.SetValue("", "安装APK");
                    RegistryKey command = open.CreateSubKey("command");
                    command.SetValue("", "\"" + exeName + "\" \"%1\"");
    
                    RegistryKey play = shell.CreateSubKey("play");
                    play.SetValue("", "用APKInstaller打开");
                    command = play.CreateSubKey("command");
                    command.SetValue("", "\"" + exeName + "\" \"%1\"", RegistryValueKind.String);
                }
                //修改对应文件类型的默认的关联程序
                RegistryKey apk = Registry.ClassesRoot.OpenSubKey(".apk", true);
                if (apk != null)
                {
                    apk.SetValue("", nodeName);
                }
                //通知系统,文件关联已经是作用,不然可能要等到系统重启才看到效果
                SHChangeNotify(HChangeNotifyEventID.SHCNE_ASSOCCHANGED, HChangeNotifyFlags.SHCNF_IDLIST, IntPtr.Zero, IntPtr.Zero);
    }

    例如,调用:string str = @"F:\WorkFile\PC\Setup\apk.ico";
                SetValue(@"F:\WorkFile\PC\Bin\Debug\APKInstaller.exe", "CN.APKInstaller",str);

      用Inno脚本的实现原理和上面时一样的,只是需要知道一些脚本的语法而已,脚本如下(其实我也不是很懂):

    const
      SHCNE_ASSOCCHANGED = $08000000;
      SHCNF_IDLIST = $0000; { LPITEMIDLIST }

    function SHChangeNotifyEx(wEnentID: Integer; uFlag: Cardinal; dwItem1: Integer; dwItem2: Integer): Integer;external 'SHChangeNotify@shell32.dll ';

    procedure LinkFileIcon;
    var
      FullPath: string;
      IconFilePath:string;
      success:Boolean;
    begin
      success := RegDeleteValue(HKEY_CURRENT_USER, 'Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.apk', 'Application');
      success := RegDeleteKeyIncludingSubkeys(HKEY_CURRENT_USER, 'Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.apk');
      success := RegWriteStringValue(HKEY_CLASSES_ROOT, '.apk', '', ExpandConstant('{#FileExAPP}'));
      FullPath := ExpandConstant('{app}') + '\' + ExpandConstant('{#ProductShortName}') +'.exe';
      success := RegWriteStringValue(HKEY_CLASSES_ROOT, ExpandConstant('{#FileExAPP}') + '\shell\open\command', '', '"' + FullPath+ '"' + ' "%1"');
      //IconFilePath := ExpandConstant('{app}') + '\' + ExpandConstant('{#ProjectFileIcon}');
      IconFilePath := ExpandConstant('{app}\APKInstaller.exe,0');
      success := RegWriteStringValue(HKEY_CLASSES_ROOT, ExpandConstant('{#FileExAPP}') + '\DefaultIcon', '', IconFilePath);
      SHChangeNotifyEx(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
    end;
    ///接触工程文件与应用程序的关联
    procedure UnLinkFileIcon;
    begin
      RegDeleteKeyIncludingSubkeys(HKEY_CLASSES_ROOT, ExpandConstant('{#FileExAPP}'));
      SHChangeNotifyEx(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, 0, 0);
    end;  
    调用:

    procedure CurStepChanged(CurStep: TSetupStep);
    begin
        LinkFileIcon();
    end;

    procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
    begin
        UnLinkFileIcon;
    end;

    稍后将会写一篇有关 文件拖拽到图标或者界面可以直接打开一个新的界面的 文章。排版太烂了,先自喷一个!
  • 相关阅读:
    辅助性的“比较操作符”
    辅助性的“比较操作符”
    浙江一乘客没赶上火车退票不成把票撕了 结果"悲剧"了
    美国超震撼短片-梦想
    在HTML文件中加入空格
    揭秘人造肉
    不能发布网站简讯
    KMPlayer
    文件四处盖章签字等
    冬天到了如何御寒
  • 原文地址:https://www.cnblogs.com/yuqf/p/I_Odd_Peak.html
Copyright © 2011-2022 走看看