Power Automate Desktop テキストをハッシュ化
ハッシュ化
ハッシュ化については、Copilot の会話を載せておきます。詳しくは検索してどうぞ。
はじめに
ハッシュ化の説明をするわけでも、アクションの使い方も説明しません。
以前作ったフローで色々気になる部分があったので、変更した内容を書きます。
続きものです。3 回目。フローの概要は以前の記事で書いたような気がします。
前回:Power Automate Desktop で XML - XPath 式
前々回:Power Automate Desktop で XML ファイルの編集
(いきなり)今のままだと、「実行したけど要素を追加しなかった」ときでも最後にファイルに書き込みを行っているので良くないです。変更がないときは上書きしないようにしたい。
読み取ってすぐの値と書き込み前の値を比較すれば良いわけだから XML ドキュメント同士で比較しても良いけど、まあまあでかい比較になります。
今の時点で 138,854 文字あります。今後も定義を追加していくのでもっと増えます。処理としては大したことないんでしょうけど無駄なのでハッシュ化して文字列を短くしてから比較します。
ハッシュ化
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
コマンドを使うと、出力される値に余計な文字列が入っちゃうので「テキストの解析」アクションで取り出す必要があります。
4 行目だけ取り出したい。
Guid.NewGuid
メソッドを使うと、Guid のみ出力することができます。
[System.Guid]::NewGuid().ToString()
末尾に改行があるのは気になるけど、さっきのよりは良くなった。
.NET スクリプト (C#)
.NET スクリプトを使うと、末尾に改行もつかないので使いやすいです。
g = Guid.NewGuid();
する必要はないですが、あえて文字列で出力したいなら、以下のコードにすると OK
g = Guid.NewGuid().ToString();
おわりに
前回の記事にそのまま書いていたのですが、XPath の話からこれを書くのは関係なさすぎるかなあと思い、わけました。
Discussion