需要在 ExtendScript 中为 windows 系统生成 UUID

need to generate UUID for windows system in ExtendScript

我使用下面的代码为 .indd 文件的链接生成了 DocumentIDInstanceID。这在 MacOS 上运行良好。

任何人都可以在 Windows 系统上推荐类似的 UUID 生成代码。 windows 系统上有这样的库吗?

function generateUUID() {
  var cmd = 'do shell script "uuidgen | tr -d " & quoted form of "-"';
  return app.doScript(cmd, ScriptLanguage.applescriptLanguage);
}

var genDocID = 'xmp.did:' + generateUUID();

TLDR; 下面是通过 的 ExtendScript API 在 Windows 系统上生成 UUID 的几种不同方法...

  • 解决方案 A"shells out" Windows 电源的命令shell 通过 VBScript。但是,此解决方案确实需要安装 Windows PowerShell,以及 运行 VBScript 的权限。

  • 解决方案 B 利用 InDesign 本身生成 UUID。它通过创建临时 .indd 文档并将其提取为 DocumentID 来实现此目的。此解决方案 运行 成功 cross-platform(MacOS 和 Windows),不需要额外的依赖项,并且比 解决方案 A 因为它不必像 解决方案 A 那样在不同的编码语言之间跳转。


解决方案 A:

Windows 上的默认 shell,即 cmd.exe 提供 built-in 实用程序来生成通用唯一标识符 (UUID)。这与在 MacOS 和其他 *nix 平台上可用的 Bash 实用程序 uuidgen 形成对比。

但是,可以通过 Windows 通过执行以下命令生成 UUID:

[guid]::Newguid()

以下 Adob​​e ExtendScript (win-generate-uuid.jsx) 演示了如何使用上述 PowerShell 命令生成 UUID。

注意:此解决方案需要:

  • Windows 待安装 PowerShell。
  • Windows 允许 运行 的。

win-generate-uuid.jsx

/**
 * Generates a unique identifier (UUID/GUID) by running a VBScript that
 * executes a PowerShell command.
 * @returns {String} - The generated unique identifier.
 */
function generateUUID() {
  var pwshCmd = '$guid = [guid]::Newguid(); $guid = [string]$guid';
  var vbScript = [
    'CreateObject("WScript.Shell").Run "powershell.exe -command ""' +
        pwshCmd + '"" | clip", 0, True',
    'guid = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text")',
    'returnValue = Replace(guid, "-","")'
  ].join('\r');

  return app.doScript(vbScript, ScriptLanguage.visualBasic);
}

var genDocID = 'xmp.did:' + generateUUID();
$.writeln(genDocID);

解释:

  1. win-generate-uuid.jsx中的generateUUID函数利用InDesign的doScript()方法来运行一个VBScript。

  2. 本质上执行的 VBScript 运行s 上述 PowerShell 命令(尽管版本略有修改),使用 Run() 命令。

    注意:需要使用VBScript "shell out" PowerShell 命令,因为InDesign 运行ning on Windows 只允许通过它的 doScript 方法执行 VBScript 或 JavaScript。

  3. PowerShell 命令的结果(即生成的 UUID)通过管道传输 (|) 到剪贴板。

  4. 随后;

    • 从剪贴板检索 UUID。
    • 生成的 UUID 中的所有连字符 (-) 都被删除,最后 return 将其发送到 .jsx 脚本。
  5. 为了进一步解释为什么使用 VBScript 的 Run()(结合到剪贴板的管道)而不是 VBScript 的 Exec() refer to 的原因。原因总结如下;

    • Run() 不显示 PowerShell window.
    • Exec() 确实简要展示了 PowerShell window.

解决方案 B:

UUID 生成的 cross-platform 解决方案(即 运行 在 MacOS 和 Windows 上成功的解决方案)是利用 InDesign 本身。这在下面的 generate-uuid.jsx 中进行了演示。

generate-uuid.jsx

#target indesign

$.level=0

/**
 * Loads the AdobeXMPScript library.
 * @returns {Boolean} True if the library loaded successfully, otherwise false.
 */
function loadXMPLibrary() {
  if (!ExternalObject.AdobeXMPScript) {
    try {
      ExternalObject.AdobeXMPScript = new ExternalObject('lib:AdobeXMPScript');
    } catch (e) {
      alert('Failed loading AdobeXMPScript library\n' + e.message, 'Error', true);
      return false;
    }
  }
  return true;
}

/**
 * Generates a unique identifier (UUID/GUID) cross-platforms (macOS/Windows).
 * @returns {String} - The generated unique identifier.
 */
function generateUUID() {
  var tmp_FilePath = File(Folder.temp + '/__temp__.indd');

  // 1. Create temporary .indd and save it to disk.
  var newDoc = app.documents.add(false);
  newDoc.save(tmp_FilePath);
  newDoc.close();

  // 2. Extract the DocumentID from temporay .indd
  var xmpFile = new XMPFile(tmp_FilePath.fsName, XMPConst.FILE_INDESIGN, XMPConst.OPEN_FOR_READ);
  var xmp = xmpFile.getXMP();
  var documentID = xmp.getProperty(XMPConst.NS_XMP_MM, 'DocumentID', XMPConst.STRING);

  // 3. Delete temporary .indd
  tmp_FilePath.remove();

  // 4. Return the DocumentID without the default `xmp.did:` prefix.
  return String(documentID).replace(/xmp\.did:/g, '');
}


if (loadXMPLibrary()) {
   var genDocID = 'xmp.did:' + generateUUID();
   $.writeln(genDocID);
}

解释:

generate-uuid.jsx 脚本(上面)包含一个名为 generateUUID 的函数,它主要执行以下操作:

  1. 创建一个新的 InDesign 文档 (.indd) 并将其保存到 OS 的临时文件夹,然后将其关闭。此任务在后台执行,因此用户不会知道实际文档已创建。

    注意 OS 的默认临时目录是通过 Folder.temp 确定的。为了进一步了解每个 OS 临时文件夹所在的位置,您可以临时将以下代码行添加到您的脚本中,它会将其路径名记录到您的 ExtenScript 控制台:

     $.writeln(Folder.temp);
    
  2. 接下来我们利用 XMP scripting API - which you should be familiar with from my answers to your previous questions; , , and .

    从新创建的临时 .indd 文件中提取 DocumentID
  3. 然后我们删除名为__temp__.indd.

    的临时.indd文件
  4. 最后,提取的 documentID 中的默认 xmp.did: 前缀被删除。

    注意: 默认的 xmp.did: 前缀在 generateUUID 函数体中被删除,然后恢复 - 这看起来有点奇怪!我特意这样做是为了让 generateUUID 更易于重用。例如;您可能还想使用它来生成 InstanceID 等,在这种情况下,您可能希望在 UUID 前加上 xmp.iid:.

我已经使用下面的简单 JS 函数来避免 Mac 和 Windows 的问题,并为其提供多个函数。

// JS - Generate Global Random Unique Number
function generateJsUUID(){
    var dt = new Date().getTime();
    var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
        var r = (dt + Math.random()*16)%16 | 0;
        dt = Math.floor(dt/16);
        return (c=='x' ? r :(r&0x3|0x8)).toString(16);
    });
    return uuid;
}