【问题标题】:Run code on either uninstall or re-install of Mac app在卸载或重新安装 Mac 应用程序时运行代码
【发布时间】:2015-12-04 03:19:54
【问题描述】:

对于使用 Cocoa/Objective-C 编写的 Mac 应用程序,常见的客户支持问题是他们尝试“卸载并重新安装”以希望恢复到干净状态。但问题是新安装仍然在读取之前安装留下的配置文件和数据库。客户刚遇到同样的问题,导致他首先卸载。然后我必须指导他删除哪些文件以恢复正常状态和/或向他展示从 UI 重置的正确方法。

虽然真正的痛点和错误会随着时间的推移而得到修复,但我想知道 如果可以执行以下任一操作:

  1. MyApp.app 被移动到垃圾箱时,是否可以运行一些代码来清理用户主目录中应用程序留下的任何垃圾?或者清单/pinfo 文件中可以指定删除某些目录或文件的内容?

  1. 当应用程序启动时,它能否以编程方式检测到它已被“重新安装”,以便为新安装执行必要的清理代码?

【问题讨论】:

    标签: macos cocoa


    【解决方案1】:

    在应用启动时,您可以考虑:

    1. 应用版本号
    2. 应用路径
    3. 应用的inode,即.app目录的inode

    将这些旧值存储在应用的首选项/应用程序支持中,与启动时的当前值进行比较。根据启发式方法,您可以决定/猜测应用程序是否已更新(第 1 次)、移动/复制/多个副本(第 2 次)、删除和重新创建(第 3 次)或其他。这并不完美,可能一个重新创建的应用程序具有相同的 inode 编号,但它不太可能而且如果它确实改变了你知道它是一个不同的目录。 p>

    HTH

    【讨论】:

      【解决方案2】:
      NSString * appPath = [[NSBundle mainBundle] bundlePath];
      NSDictionary * fileAttribs = [[NSFileManager defaultManager]  
          attributesOfItemAtPath:appPath error:nil
      ];
      NSDate * creationDate = [fileAttribs objectForKey:NSFileModificationDate];
      
      NSDate * savedDate = [[NSUserDefaults standardUserDefaults] 
          objectForKey:@"AppBundleFileModificationDate"
      ];
      
      if (!savedDate) {
          // ... App never ran before ...
      } else if (![creationDate isEqual:savedDate]) {
          // ... App did run before, 
          // but bundle has been re-installed or updated ...
      } else {
          // ... App did run before and has not 
          // been re-installed or updated ...
      }
      
      [[NSUserDefaults standardUserDefaults]
          setObject:creationDate forKey:@"AppBundleFileModificationDate"
      ];
      

      如何区分重新安装和更新?保存应用版本,如果是更新,它已经改变,它不是,它是相同版本的重新安装。

      如果用户将应用移动到不同的目录并从那里启动,代码将错误地检测到重新安装。如果您还存储 appPath 并进行比较,您就可以捕捉到这种情况。

      只要用户不删除应用程序的首选项,您写给 NSUserDefaults 的内容就会继续存在,这在 Mac 上永远不会自动发生。

      【讨论】:

      • @CRD 但是移动会改变路径,这在我的回复中明确提到(不在代码中,在下面的文本中也属于我的回复)。创建日期不一定是磁盘上文件的创建日期,例如ZIP 和 TAR 通常会保留文件的原始创建日期,如果我解压缩 ZIP 文件,然后从中删除应用程序并再次 umcompress 相同的 ZIP 文件(这将是重新安装的情况),如果我使用了创建日期。
      • @CRD 例如您无法使用像 NSFileManager 这样的高级 API 获得 inode 编号,并非所有文件系统都有真实的 inode 编号,在这种情况下,系统会伪造一些(想想 FAT32 U 盘,想想像 WebDAV 这样的网络文件系统)和 inode不能保证是稳定的(伪造的 inode 很少是稳定的,除此之外,它取决于文件系统是否以及何时 inode 可能发生变化,例如,当文件被移动或通过自动碎片整理或某些 COW 机制时)。另见stackoverflow.com/q/16069898
      • @CRD Mac 支持 FAT32 就好了。您可以本地访问 FAT32 格式的 HD 或 USB 记忆棒,也可以从中启动应用程序(我一直使用 USB 记忆棒这样做)。很多用户都有一个远程家(我在工作中也是如此),他们还可以在其中安装应用程序(Mac 应用程序也可以从您的桌面或主目录运行)但远程服务器也可能是具有 NTFS 的 Windows 文件服务器和 SMB 访问。修改日期(适用于所有文件系统 AFAIK)表示上次修改的日期,使用它来检测修改对我来说似乎是最自然的(顾名思义)。
      猜你喜欢
      • 2014-07-15
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-12
      • 2019-07-03
      • 1970-01-01
      相关资源
      最近更新 更多