🍭

Power Automate Desktop テキストをハッシュ化

2024/07/23に公開

ハッシュ化

ハッシュ化については、Copilot の会話を載せておきます。詳しくは検索してどうぞ。


はじめに

ハッシュ化の説明をするわけでも、アクションの使い方も説明しません。
以前作ったフローで色々気になる部分があったので、変更した内容を書きます。
続きものです。3 回目。フローの概要は以前の記事で書いたような気がします。

前回:Power Automate Desktop で XML - XPath 式
前々回:Power Automate Desktop で XML ファイルの編集


(いきなり)今のままだと、「実行したけど要素を追加しなかった」ときでも最後にファイルに書き込みを行っているので良くないです。変更がないときは上書きしないようにしたい。

読み取ってすぐの値と書き込み前の値を比較すれば良いわけだから XML ドキュメント同士で比較しても良いけど、まあまあでかい比較になります。

今の時点で 138,854 文字あります。今後も定義を追加していくのでもっと増えます。処理としては大したことないんでしょうけど無駄なのでハッシュ化して文字列を短くしてから比較します。

ハッシュ化
Hashed Text

44文字です。元の値と比べるとめちゃくちゃ短くなりました。
この値が一致したら変更していないことになります。

こんな感じになりました。値が等しくなければファイルに書き込む。
完成

FUNCTION Registration GLOBAL
    XML.ReadFromFile File: $'''%OneDrive%%MasterFile%''' Encoding: XML.FileEncoding.DefaultEncoding XmlDocument=> XmlDocument
    ON ERROR DirectoryNotFoundError
        SET ErrorMsg TO $'''ディレクトリが見つかりません。'''
        CALL Catch
        THROW ERROR
    ON ERROR FileNotFoundError
        SET ErrorMsg TO $'''ファイルが見つかりません。'''
        CALL Catch
        THROW ERROR
    ON ERROR ReadFileError
        SET ErrorMsg TO $'''ファイルを読み取れませんでした。'''
        CALL Catch
        THROW ERROR
    ON ERROR InvalidFileError
        SET ErrorMsg TO $'''ファイルに有効な XML ドキュメントが含まれていません。'''
        CALL Catch
        THROW ERROR
    END
    Cryptography.HashText HashAlgorithm: Cryptography.HashAlgorithm.SHA256 Encoding: Cryptography.EncryptionEncoding.Unicode TextToHash: XmlDocument HashedText=> HashedTextA
    LOOP FOREACH タイトル IN 作品リスト
        CALL Now
        XML.ExecuteXPathQuery.ExecuteXPathAndGetFirstValueOnly XmlDocument: XmlDocument XPathQuery: $'''//Strategy[contains(Regex, \"%タイトル%\")]''' XPathResult=> XPathResult
        IF StartsWith(XPathResult, $'''<''', False) THEN
            Text.AppendLine Text: Log LineToAppend: $'''%CurrentDateTime% INFO Skip %タイトル%''' Result=> Log
            NEXT LOOP
        END
        **REGION フォルダーの作成
        IF (Folder.IfFolderExists.DoesNotExist Path: $'''%Server%%StoreDir%\\%タイトル%''') THEN
            Text.AppendLine Text: Log LineToAppend: $'''%CurrentDateTime% INFO mkdir %タイトル%''' Result=> Log
            Folder.Create FolderPath: $'''%Server%%StoreDir%''' FolderName: タイトル
            ON ERROR REPEAT 3 TIMES WAIT 15
            ON ERROR
                SET ErrorMsg TO $'''フォルダー「%タイトル%」を作成できません。'''
                CALL Catch
                THROW ERROR
            END
        END
        **ENDREGION
        Text.AppendLine Text: Log LineToAppend: $'''%CurrentDateTime% INFO Set %タイトル%''' Result=> Log
        **REGION 定義ファイルに追加
        Scripting.RunDotNetScript Language: System.DotNetActionLanguageType.CSharp Script: $'''g = Guid.NewGuid();''' @'name:g': $'''''' @'type:g': $'''Dynamic''' @'direction:g': $'''Out''' @g=> GUID
        XML.InsertElement Document: XmlDocument XPathQuery: $'''Strategies''' Element: $'''<Strategy name=\"%GUID%\">
    <Regex>%タイトル%</Regex>
    <DestDir>%DestDir%</DestDir>
    <DestDir>%Fqdn%%StoreDir%\\%タイトル%</DestDir>
  </Strategy>'''
        **ENDREGION
    END
    Cryptography.HashText HashAlgorithm: Cryptography.HashAlgorithm.SHA256 Encoding: Cryptography.EncryptionEncoding.Unicode TextToHash: XmlDocument HashedText=> HashedTextB
    IF HashedTextA <> HashedTextB THEN
        XML.WriteXmlToFile.WriteToFileFormatted File: $'''%OneDrive%%MasterFile%''' Xml: XmlDocument Encoding: XML.FileEncoding.UTF8 Indentation: 2
        ON ERROR REPEAT 3 TIMES WAIT 15
        END
    END
END FUNCTION

その他、Guid 作成の部分も気になったので PowerShell から .NET スクリプトに変えました。

Guid の作成方法

PowerShell

New-Guidコマンドを使うと、出力される値に余計な文字列が入っちゃうので「テキストの解析」アクションで取り出す必要があります。

PowerShell スクリプト

4 行目だけ取り出したい。
変数の値

Guid.NewGuidメソッドを使うと、Guid のみ出力することができます。

[System.Guid]::NewGuid().ToString()

末尾に改行があるのは気になるけど、さっきのよりは良くなった。

.NET スクリプト (C#)

.NET スクリプトを使うと、末尾に改行もつかないので使いやすいです。
System.Guid

g = Guid.NewGuid();

コード
スクリプト パラメーター

する必要はないですが、あえて文字列で出力したいなら、以下のコードにすると OK

g = Guid.NewGuid().ToString();

テキスト値


おわりに

前回の記事にそのまま書いていたのですが、XPath の話からこれを書くのは関係なさすぎるかなあと思い、わけました。

Discussion