杉宫竹苑工作室

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2493|回复: 0

Inno Setup 实现 Hosts 备份与改写

[复制链接]
发表于 2017-1-9 20:27:14 | 显示全部楼层 |阅读模式

正式会员享受无限制浏览网站功能和高速网盘下载,赶快加入本站吧!

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #ifdef Unicode
  2. #define A "W"
  3. #else
  4. #define A "A"
  5. #endif


  6. [Setup]
  7. AppName=My Program
  8. AppVerName=My Program version 1.5
  9. DefaultDirName={pf}\My Program
  10. DefaultGroupName=My Program

  11. [code]
  12. const
  13. myMark = '由 XYZ 添加';   // 作为标识

  14. function GetFileAttributes(lpFileName: String): Cardinal;
  15. external 'GetFileAttributes{#A}@kernel32.dll stdcall';

  16. function SetFileAttributes(lpFileName: String; dwFileAttributes: Cardinal): Boolean;
  17. external 'SetFileAttributes{#A}@kernel32.dll stdcall';

  18. function LineInFile(sLine, fPath: string): Boolean;
  19. var
  20. aos: TArrayOfString;
  21. n: Integer;
  22. begin
  23. Result:= false;
  24. if LoadStringsFromFile(fPath, aos) then
  25. for n:= 0 to GetArrayLength(aos)-1 do
  26.   if aos[n] = sLine then
  27.     begin
  28.     Result := true;
  29.     Exit;
  30.     end;
  31. end;

  32. procedure AddHosts(newItem, comments: string);
  33. var
  34. OldFileAttribute: Cardinal;
  35. hfPath, newLine: string;
  36. begin
  37. hfPath := ExpandConstant('{sys}\drivers\etc\hosts');
  38. if not LineInFile(newItem, hfPath) then       // 仅添加 Hosts 中还没有的项目
  39.   begin
  40.   OldFileAttribute:= GetFileAttributes(hfPath);
  41.   SetFileAttributes(hfPath, FILE_ATTRIBUTE_NORMAL);
  42.   newLine := newItem + ' # ' + myMark;
  43.   If comments > ' ' then
  44.     newLine := newLine + ' / ' + comments;
  45.   SaveStringToFile(hfPath, #13#10 + newLine, True);
  46.   SetFileAttributes(hfPath, OldFileAttribute);
  47.   end;
  48. end;

  49. procedure RemoveHosts(sItem: string);
  50. var
  51. OldFileAttribute: Cardinal;
  52. hfPath, newLine: string;
  53. stl: TStringList;
  54. n: Integer;
  55. begin
  56. hfPath := ExpandConstant('{sys}\drivers\etc\hosts');
  57. newLine := sItem + ' # ' + myMark;
  58. stl:= TStringList.Create;
  59. stl.LoadFromFile(hfPath);
  60. for n:= stl.Count-1 downto 0 do
  61.   if Pos(newLine, stl.Strings[n]) = 1 then
  62.     stl.Delete(n);
  63. OldFileAttribute:= GetFileAttributes(hfPath);
  64. SetFileAttributes(hfPath, FILE_ATTRIBUTE_NORMAL);
  65. stl.SaveToFile(hfPath);
  66. stl.Free;
  67. SetFileAttributes(hfPath, OldFileAttribute);
  68. end;

  69. procedure Initializewizard;
  70. begin
  71. AddHosts('0.0.0.0 www.xxx.com', '这是注释'); // 在 Hosts 中添加新项目,带注释
  72. AddHosts('0.0.0.0 www.111.com', '');       // 在 Hosts 中添加新项目,不带注释
  73. end;

  74. procedure DeinitializeUninstall;
  75. begin
  76. RemoveHosts('0.0.0.0 www.xxx.com'); // 从 Hosts 中删除项目
  77. RemoveHosts('0.0.0.0 www.111.com');       // 从 Hosts 中删除项目
  78. end;
复制代码


优化后的代码:
- ANSI 和 Unicode 版本都适用。
- 增加了计数功能,保证卸载时只会删除自己添加的项目。
- 采用文件流,无论多大的 Hosts 文件都可以处理。
- 无论添加或删除多少个项目,只需要读取 Hosts 文件一次,从而加快运行速度,避免出现假死现象。

  1. #define AppID "FDBDCE28-5522-494B-B75A-E515082A312D"

  2. #ifdef UNICODE
  3.   #define A "W"
  4. #else
  5.   #define A "A"
  6. #endif

  7. [Setup]
  8. AppId={#AppID}
  9. AppName=My Program
  10. AppVerName=My Program version 1.5
  11. DefaultDirName={pf}\My Program
  12. DefaultGroupName=My Program

  13. [Tasks]
  14. Name: noad; Description: "通过 hosts 屏蔽广告(&D)"

  15. [code]
  16. const
  17.   myMark = 'XYZ123';   // 你的标识,用于标识你修改的内容

  18. Var
  19.   AddHostsItemList, AddHostsCommentList, RemoveHostsList: TStringList;

  20. function GetFileAttributes(lpFileName: String): Cardinal;
  21.   external 'GetFileAttributes{#A}@kernel32.dll stdcall';

  22. function SetFileAttributes(lpFileName: String; dwFileAttributes: Cardinal): Boolean;
  23.   external 'SetFileAttributes{#A}@kernel32.dll stdcall';

  24. function IsLineInFile(sItem: string; sl: TStringList; var LineNo, Cnt: LongInt): Boolean;
  25. var
  26.   s: String;
  27.   n: Integer;
  28. begin
  29.   Result := false;
  30.   LineNo := 0;          // 行号
  31.   Cnt := 0;             // 计数器
  32.   for n:= 0 to sl.Count-1 do
  33.     if Pos(sItem, Trim(sl.Strings[n])) = 1 then
  34.       begin
  35.         Result := true;
  36.         LineNo := n + 1;
  37.         s := Trim(sl.Strings[n]);
  38.         if Pos('##', s) > 0 then
  39.           begin
  40.             Delete(s, 1, Pos('##', s)+1);
  41.             if Pos(' ', s) > 0 then
  42.               s := Copy(s, 1, Pos(' ', s)-1);
  43.             Cnt := StrToIntDef(s, 0);
  44.           end;
  45.         exit;
  46.       end;
  47. end;

  48. procedure StartAddHosts();
  49. begin
  50.   AddHostsItemList := TStringList.Create;
  51.   AddHostsCommentList := TStringList.Create;
  52. end;

  53. procedure AddHosts(newItem, comments: string);
  54. begin
  55.   AddHostsItemList.Add(newItem);
  56.   AddHostsCommentList.Add(comments);
  57. end;

  58. procedure EndAddHosts();
  59. var
  60.   stl: TStringList;
  61.   fs: TFileStream;
  62.   OldFileAttribute: Cardinal;
  63.   hfPath, newItem, comments, s: string;
  64.   LineNo, Cnt, n: LongInt;
  65. begin
  66.   hfPath := ExpandConstant('{sys}\drivers\etc\hosts');
  67.   OldFileAttribute := GetFileAttributes(hfPath);
  68.   SetFileAttributes(hfPath, FILE_ATTRIBUTE_NORMAL);
  69.   stl := TStringList.Create;
  70.   stl.LoadFromFile(hfPath);
  71.   try
  72.     for n:= 0 to AddHostsItemList.Count-1 do
  73.       begin
  74.         newItem := AddHostsItemList.Strings[n];
  75.         comments := AddHostsCommentList.Strings[n];
  76.         if IsLineInFile(newItem, stl, LineNo, Cnt) then          // 检查 Hosts 中是否有该项
  77.           begin
  78.             s := stl.Strings[LineNo-1];
  79.             if Cnt = 0 then
  80.               StringChangeEx(s, newItem, newItem + ' ##2', true)   // 如果有项目,但是没有计数,说明是别人已经添加的项目,计数从 2 开始
  81.             else
  82.               StringChangeEx(s, newItem + ' ##' + IntToStr(Cnt), newItem + ' ##' + IntToStr(Cnt+1), true);  // 计数加 1
  83.             stl.Strings[LineNo-1] := s;
  84.           end
  85.         else
  86.           begin                                          // Hosts 中还没有该项
  87.             s := newItem + ' ##1 ID' + myMark;           // 计数从 1 开始,ID标识
  88.             if Trim(comments) > '' then                  // 检查注释是否为空白
  89.               s := s + ' / ' + Trim(comments);
  90.             stl.Add(s);
  91.           end;
  92.         end;
  93.     finally
  94.       AddHostsItemList.Free;
  95.       AddHostsCommentList.Free;
  96.     end;
  97.   fs := TFileStream.Create(hfPath, fmCreate);
  98.   try
  99.     stl.SaveToStream(fs);
  100.     fs.Size := fs.Size - Length(#13#10);         // 删除最后的换行符
  101.   finally
  102.     stl.Free;
  103.     fs.Free;
  104.   end;
  105.   SetFileAttributes(hfPath, OldFileAttribute);
  106. end;

  107. procedure StartRemoveHosts();
  108. begin
  109.   RemoveHostsList := TStringList.Create;
  110. end;

  111. procedure RemoveHosts(sItem: string);
  112. begin
  113.   RemoveHostsList.Add(sItem);
  114. end;

  115. procedure EndRemoveHosts();
  116. var
  117.   OldFileAttribute: Cardinal;
  118.   hfPath, sItem, s: string;
  119.   stl: TStringList;
  120.   fs: TFileStream;
  121.   LineNo, Cnt, n: LongInt;
  122. begin
  123.   hfPath := ExpandConstant('{sys}\drivers\etc\hosts');
  124.   OldFileAttribute := GetFileAttributes(hfPath);
  125.   SetFileAttributes(hfPath, FILE_ATTRIBUTE_NORMAL);
  126.   stl := TStringList.Create;
  127.   stl.LoadFromFile(hfPath);
  128.   try
  129.     for n:= 0 to RemoveHostsList.Count-1 do
  130.       begin
  131.         sItem := RemoveHostsList.Strings[n];
  132.         if IsLineInFile(sItem, stl, LineNo, Cnt) then     // 检查 Hosts 中是否有该项
  133.           if Cnt > 0 then
  134.             begin
  135.               if Cnt = 1 then
  136.                 stl.Delete(LineNo-1)                      // 计数是 1 的项将被删除
  137.               else
  138.                 begin
  139.                   s := stl.Strings[LineNo-1];
  140.                   if (Cnt = 2) and (Pos('ID'+myMark, s) = 0) then     // 如果计数是 2,但是没有标识,说明是别人添加的项,将恢复原状
  141.                     StringChangeEx(s, sItem + ' ##2', sItem, true)
  142.                   else
  143.                     StringChangeEx(s, sItem + ' ##' + IntToStr(Cnt), sItem + ' ##' + IntToStr(Cnt-1), true);   // 计数减 1
  144.                   stl.Strings[LineNo-1] := s;
  145.                 end;
  146.             end;
  147.         end;
  148.   finally
  149.     RemoveHostsList.Free;
  150.   end;
  151.   fs := TFileStream.Create(hfPath, fmCreate);
  152.   try
  153.     stl.SaveToStream(fs);
  154.     fs.Size := fs.Size - Length(#13#10);    // 删除最后的换行符
  155.   finally
  156.     stl.Free;
  157.     fs.Free;
  158.   end;
  159.   SetFileAttributes(hfPath, OldFileAttribute);
  160. end;

  161. function GetHKLM: Integer;
  162. begin
  163.   if IsWin64 then
  164.     Result := HKLM32
  165.   else
  166.     Result := HKLM;
  167. end;

  168. function WasTaskSelected(aTask, AppID: String): boolean;
  169. var
  170.   sSelectedTasks, sTask: String;
  171. begin
  172.   Result := false;
  173.   sSelectedTasks := '';
  174.   if RegQueryStringValue(getHKLM, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\'+AppID+'_is1',
  175.         'Inno Setup: Selected Tasks', sSelectedTasks) then
  176.     begin
  177.       sSelectedTasks := Uppercase(sSelectedTasks);
  178.       sTask := Uppercase(aTask);
  179.       if Pos(',', sSelectedTasks) = 0 then
  180.         Result := sSelectedTasks = sTask
  181.       else
  182.         begin
  183.           if Pos(sTask+',', sSelectedTasks) = 1 then
  184.             Result := true;
  185.           if Pos(','+sTask+',', sSelectedTasks) > 0 then
  186.             Result := true;
  187.           if Pos(','+sTask, sSelectedTasks) = Length(sSelectedTasks) - Length(sTask) then
  188.             Result := true;
  189.         end;
  190.     end;
  191. end;

  192. procedure CurStepChanged(CurStep: TSetupStep );
  193. begin
  194.   if CurStep = ssPostInstall then         // 安装文件前检查
  195.     if IsTaskSelected('noad') then        // 是否选择了相应的任务
  196.       begin
  197.         StartAddHosts;                                        // 开始添加项目(必需)
  198.         AddHosts('127.0.0.1 www.abcd.com', '你的注释');       // 添加要增加的项目,带注释
  199.         AddHosts('127.0.0.1 www.abcd.net', '');               // 添加要增加的项目,不带注释
  200.         EndAddHosts;                                          // 结束添加项目(必需)
  201.       end;
  202. end;

  203. procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep );
  204. begin           
  205.   if CurUninstallStep = usUninstall then           // 卸载文件前检查
  206.     if WasTaskSelected('noad', '{#AppID}') then    // 安装时是否选择了相应的任务
  207.       begin
  208.         StartRemoveHosts;                             // 开始删除项目(必需)
  209.         RemoveHosts('127.0.0.1 www.abcd.com');        // 添加要删除的项目
  210.         RemoveHosts('127.0.0.1 www.abcd.net');        // 添加要删除的项目
  211.         EndRemoveHosts;                               // 结束删除项目(必需)
  212.       end;
  213. end;
复制代码


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SgzyStudio

GMT+8, 2024-5-19 18:42 , Processed in 0.109845 second(s), 18 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表