azukipochette's weblog

memory dump (mini)

deepL REST API で XML タグを含む文字列を渡すと課金はどうなるかを検証

日本語への翻訳が群を抜いていると話題の deepL ですが、有償版である deepL Pro の開発者向けプランでは、deepL の翻訳サービスを REST API として呼び出す事ができます。
私は PowerPoint のスライドを翻訳するアプリを作り、内部の翻訳エンジンに deepL を使うことにしました。

www.deepl.com

deepL が提供する REST API では、パラメータに tag_handling=xml と指定することで、XML タグを考慮して翻訳してくれます。
これにより、タグによって修飾(色、フォント サイズ、強調など)されている箇所を気にせず、そのまま翻訳することができます。

しかし、気になるのが課金対象となる「文字数」です。 REST API に渡したテキストの文字数なのか、タグを除いた翻訳対象となる文字数なのかがよく分かりません。

そこで、実際に実験してみました。

まず PowerPoint のスライドを解析し、パラグラフを取得します。実際のデータは以下の通りです。

<a:r xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"><a:rPr lang="en-US" dirty="0" /><a:t>Developing Cross-Platform Web Apps With Blazor</a:t></a:r>

これを REST API で翻訳した結果 (JSON) は以下の通りです。

{
  "translations": [
    {
      "detected_source_language": "EN",
      "text": "<a:r xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\"><a:rPr lang=\"en-US\" dirty=\"0\" /><a:t>BlazorでクロスプラットフォームのWebアプリを開発する</a:t></a:r>"
    }
  ]
}

ダッシュボードで確認したところ、課金対象となっているのは 46 文字 ($0.12) でした。 「翻訳した文字数」で課金されていますので、安心して XML タグを投げられますね。 :-)

Terraform の Azure DevOps プロバイダー

Terraform に Azure DevOps プロバイダーが追加されました。

www.terraform.io

Microsoft からも公式にアナウンスがありましたが、(なぜか)Azure DevOps Blog ではなく、Open Source Blog から発表されたので、気が付かなかったという人もいるかもしれません。

cloudblogs.microsoft.com

このプロバイダーを使えば、チーム プロジェクト、グループ、リポジトリ、ビルド定義などを Terraform で管理できるようになります。まだまだ機能的に制限はありますが、プロジェクト作成時に毎回同じ設定を手作業でするのが大変...という管理者の方には便利かと思います *1

インストール方法

まだ Terraform Registory には存在しないらしいので、自分でプラグインをインストールする必要があります。 GitHub ページの Release から入手します。

github.com

インストール方法は使われているプラットフォームなどによってことなりますが、私は Terraform を WSL2 (Pengwin) 上で使っているので、以下のような流れで導入しました。

mkdir ~/.terraform.d/plugins/linux_amd64
cd ~/.terraform.d/plugins/linux_amd64
wget https://github.com/microsoft/terraform-provider-azuredevops/releases/download/v0.1.3/terraform-provider-azuredevops_v0.1.3_linux_amd64.tar.gz
tar zxvf terraform-provider-azuredevops_v0.1.3_linux_amd64.tar.gz
chmod +x terraform-provider-azuredevops_v0.1.3

使い方

チームプロジェクトを新規に作成し、作成したプロジェクトに Git リポジトリを追加する場合は以下のような tf ファイルを記述します。

provider "azuredevops" {
    version = ">= 0.0.1"
}

resource "azuredevops_project" "project" {
    project_name = "Sample Project"
    description = "This is Sample Project"
    visibility = "private"
    version_control = "Git"
    work_item_template = "Scrum"
}

resource "azuredevops_git_repository" "repo" {
  project_id = azuredevops_project.project.id
  name       = "Sample Empty Git Repository"
  initialization {
    init_type = "Clean"
  }
}

対象の Azure DevOps 組織の URL や実行に使用するパーソナル アクセス トークン (PAT) は環境変数として設定します。*2

export AZDO_ORG_SERVICE_URL="https://dev.azure.com/<your org>/"
export AZDO_PERSONAL_ACCESS_TOKEN="<your PAT>"

おまけ

現時点でのリソースの一覧を以下に示します。
なお、実際に使うとすぐに気が付きますが、ドキュメントに記載はあっても、使おうとするとリリース バージョンにまだ実装されていないことがあるので、ドキュメントは参考程度に参照するとよいと思います。

  • azuredevops_agent_pool
  • azuredevops_agent_queue
  • azuredevops_git_repository
  • azuredevops_branch_policy_build_validation
  • azuredevops_branch_policy_min_reviewers
  • azuredevops_build_definition
  • azuredevops_group
  • azuredevops_group_membership
  • azuredevops_project
  • azuredevops_project_features
  • azuredevops_resource_authorization
  • azuredevops_serviceendpoint_azurerm
  • azuredevops_serviceendpoint_bitbucket
  • azuredevops_serviceendpoint_dockerhub
  • azuredevops_serviceendpoint_github
  • azuredevops_serviceendpoint_kubernetes
  • azuredevops_user_entitlement
  • azuredevops_variable_group

*1:リリースされたばかりで、できなことがたくさんありますが...

*2:PAT の権限は使用するリソースに依存します。最適な権限を設定してください。

Elgato Stream Deck で UWP アプリを起動する

まくら

Scott Hanselman 先生に影響を受けて Elgato Stream Deck を買いました。

もし、Scott Hanselman 先生の記事にご興味があれば、こちらを見てください。
テレワーク (WFH) でプレゼンをするためのノウハウなどが聞けます。

www.hanselman.com

www.hanselman.com

本題

Elgato Stream Deck を使うと、好きなアプリを登録することでワンボタンで起動できるようになるのですが、UWP アプリ (ストア アプリ) を簡単に登録することができません。
しかし、たいていの UWP アプリには URI スキームと呼ばれる URI を使った起動方法があるので、これを使って登録する方法を今回は紹介します。

たとえば、代表的な UWP アプリである「電卓」を起動したい場合、Win+R キーを押して表示される "ファイル名を指定して実行" ウィンドウの [名前] に calculator: として入力して [OK] をクリックすると電卓が起動します。これが URI スキームを利用したアプリの起動です。

ここで問題になるのが、「使っているアプリの URI スキームが何かがわからない!」ということでしょう。 Microsoft が標準で提供しているアプリの場合、インターネット検索すると出てきたりしますが、"Microsoft ストア" などを通じてインストールしたアプリなどは開発者が明示的に公開していない場合も多いので、まずは自分が使っているアプリの URI スキームの調べ方から説明します。

UWP アプリの URI スキームの一覧を取得する

PowerShell を起動して以下のコマンドを実行すると、"Protocol" のところにアプリが登録している URI スキームが表示されます。

Get-AppxPackage | Select-Object -Property Name, PackageFullName, @{
    Label='Protocol'
    Expression={(Get-AppxPackageManifest $_).package.applications.application.extensions.extension.Protocol.name}
} | Format-List

UWP アプリは標準で複数インストールされているため、大量に結果が表示されると思います。
アプリを絞り込みたい場合は、Get-AppxPackage の部分を Get-AppxPackge *<Keyword>* のようにすることで、検索に一致したアプリだけが表示されるようになります。

たとえば、"Minecraft" を調べたい場合は以下のようにして実行します。 (前後に * を追加することで、部分一致で検索することができます。)

Get-AppxPackage *Minecraft* | Select-Object -Property Name, PackageFullName, @{
    Label='Protocol'
    Expression={(Get-AppxPackageManifest $_).package.applications.application.extensions.extension.Protocol.name}
} | Format-List

出力結果を以下に示します(環境によって結果は異なります)

Name            : Microsoft.MinecraftUWP
PackageFullName : Microsoft.MinecraftUWP_1.15.9.0_x64__8wekyb3d8bbwe
Protocol        : {ms-xbl-multiplayer, minecraft}

なお、アプリによっては 1アプリで複数の URI スキームを登録している場合があります。
出力結果から肝心の URI スキーマ部分が省略されてしまっている場合は、Format-List の部分を Out-GridView などにしてみてください。

URI スキーマで起動してみる

アプリによっては機能毎に URI スキーマを登録しているものもあります。 実際にどの URI スキーマがどの働きをもつのかは実際に試してみる必要があります。

先ほどと同様に Win+R キーを押して "ファイル名を指定して実行" ウィンドウの [名前] に "<プロトコル名>:" と入力します。
このとき、最後の : (コロン) を絶対に忘れないようにしましょう!忘れると起動に失敗するか、異なるアプリを起動してしまいます。*1

コマンドプロンプトから起動したい場合は、以下のよう実行します。

start <プロトコル>:

プロトコル名の前に start を付けることがポイントです。

Elgato Stream Deck に登録する

URI スキーマで起動できることが確認できたら、いよいよ Elagto Stream Deck に登録します。

  1. Stream Deck アプリを立ち上げます
  2. 右ペインから System > Website を選び、ドラッグして配置したい場所にドロップします。
  3. URL に上記で調べた URI スキーマを入力します (コロンを忘れずに!)

ポイントは URI スキーマを利用するので、"Open" ではなく "Website" を選ぶというところです。後は、アイコンなどお好きにカスタマイズしてください。

それでは楽しい Stream Deck 生活を。Enjoy!

*1:: (コロン)がない場合、Windows は実行ファイルを探し、起動しようとします

Microsoft 356 専用キー (Office 専用キー) の使い方と代替方法

Surface リリース祭りに隠れて、新しいマイクロソフト製キーボードがリリースされました。 このキーボードの最大の特徴は、従来のアプリケーション キーの代わりに "Microsoft 365 (旧 Office 365) 専用キー" を備えていることです。

この記事は、Microsoft 365 専用キー (以下、Office キーと記載) に興味はあるものの、キーボードを新しく買うほどではない...そんなアナタに贈ります。

Office キーで出来ること

Office キーを使うことで、Microsoft Word などの Microsoft Office 製品やサービスを起動することができます。
ショートカットを以下に示します。*1

ショートカット 結果
Office Office アプリを開く
Office+W Microsoft Word を開く
Office+X Microsoft Excel を開く
Office+P Microsoft PowerPoint を開く
Office+O Microsoft Outlook を開く
Office+D OneDrive を開く
Office+N Microsoft OneNote を開く
Office+L LinkedIn (ウェブサイト) を開く
Office+T Microsoft Teams を開く
Office+Y Yammer (ウェブサイト) を開く
Office+Esc アクティブなウィンドウの切り替え

Office キーがない場合の代替方法

手元のキーボードに Win (Windows) キーがないとき、Ctrl+Esc を押下すると Win キーの代わりになるという事実をご存じですか?
Office キーにも代替のキー コンビネーションがあり、Ctrl+Alt+Shift+Win が割り当てられています。*2

Office キーの仮想キーコード/スキャン コード

実は、Office キー専用のキーコードやスキャン コードは存在せず、単に上記のキー コンビネーションを送っているだけです。

実際に Office キーが存在する最新キーボード "Microsoft Bluetooth® Keyboard" を使って Keymill (キー入力を調べるツール) で調査しました。
以下の画像がその結果です。

f:id:AzukiPochette:20200513161317p:plain

実際に、Ctrl (左) + Alt (左) + Shitf (左) + Win (左) が押されていることが分かります。

AutoHotKey で右 Win キー (RWIN) を Office キーに置き換える

AutoHotKey (AHK) を使って、右側の Win キーを Office キーに変換するスクリプト例を以下に記載します。
私は Happy Hacking Keyboard (HHK) *3 を使っているので右 Win キーを置換しましたが、RWin の部分を変えればお好きなキー(例えば、アプリケーション キー)を Office キーに変えられます。

RWin:: ; Right Windows key down
    Send, {LCtrl Down}{LShift Down}{LAlt Down}{LWin Down}
    Return

RWin Up:: ; Right Windows key up
    Send, {LCtrl Up}{LShift Up}{LAlt Up}{LWin Up}
    Return

それでは良い Office キー共同生活を。Enjoy!

*1:LinkedIn は Office シリーズだったのか...?という謎が...

*2:なんとも押しにくい!と思ったアナタ。私も同感です。割り当てる先がもうあまり無いというのが理由だと思いますが、もう片手で押すのは厳しいですね

*3:Happy Hacking Keyboard Professional HYBRID Type-S

RDP ファイルにパスワードを埋め込んで自動ログオンする

リモート デスクトップ接続で自動ログオンしたい場合は、RDP ファイルを作成し、ファイルの中にパスワードを埋め込む必要があります。

埋め込むパスワードは事前に暗号化する必要があります。
暗号化したパスワードを取得するには、PowerShell で下記スクリプトの YOUR PASSWORD 部分を実際のパスワードに変更して実行します。 実行すると、暗号化されたパスワードがクリップボードに保存されます。

Add-Type -AssemblyName System.Security
$password = "YOUR PASSWORD"
([System.Security.Cryptography.ProtectedData]::Protect([System.Text.Encoding]::Unicode.GetBytes($password), $null, [System.Security.Cryptography.DataProtectionScope]::CurrentUser) | ForEach-Object ToString X2) -join "" | clip 

RDP ファイルを任意のテキストエディタで開き、下記の行を追記します。 このとき、<ENCRYPTED PASSWORD> の部分をクリップボードの内容で置換します。

password 51:b:<ENCRYPTED PASSWORD>

あとは、変更した RDP ファイルを使用して接続するだけです。

Azure DevOps Server 2019 向け管理クエリ

チーム プロジェクト コレクション単位で使用容量を調べる

以下のクエリを実行する。

USE master
SELECT DB_NAME(database_id) AS DBName, 
       (SIZE / 128) SizeInMB 
FROM sys.master_files WITH (NOLOCK) 
WHERE TYPE = 0 
  AND SUBSTRING(DB_NAME(database_id), 1, 12) = 'AzureDevOps_' 
  AND DB_NAME(database_id) <> 'AzureDevOps_Configuration' 
ORDER BY SIZE DESC 

なお、Azure DevOps Server 2019 を新規で構築した場合、DB の Prefix は AzureDevOps_ だが、Team Foundation Server 2018 以前からアップグレードした場合は Tfs_ となる。
Team Foundation Server 2018 以前からアップグレートしている場合は、以下のクエリを実行する。

USE master
SELECT DB_NAME(database_id) AS DBName,
       (size / 128) SizeInMB
FROM sys.master_files WITH (NOLOCK)
WHERE type = 0
  AND SUBSTRING(DB_NAME(database_id), 1, 4) = 'Tfs_'
  AND DB_NAME(database_id) <> 'Tfs_Configuration'
ORDER BY size DESC

Git リポジトリ毎に使用容量を調べる

下記のクエリを各チーム プロジェクト コレクション DBで実行する。

SELECT r.Name, 
       COUNT(*) AS FileCount, 
       SUM(fm.FileLength) AS FileSize, 
       SUM(fm.CompressedLength) AS FileCompressedSize 
FROM tbl_GitRepository AS r WITH (NOLOCK) 
JOIN tbl_Container AS c WITH (NOLOCK) ON c.ArtifactUri = ('vstfs:///Git/GitOdbStorage/' + LOWER(REPLACE(CAST(r.ContainerId AS varchar(36)), '-', ''))) 
JOIN tbl_ContainerItem AS i WITH (NOLOCK) ON c.ContainerId = i.ContainerId 
JOIN tbl_FileReference AS fr WITH (NOLOCK) ON i.FileId = fr.FileId 
JOIN tbl_FileMetadata AS fm WITH (NOLOCK) ON fr.ResourceId = fm.ResourceId 
GROUP BY r.Name

PowerShell コマンドの実装を調べる方法

f:id:AzukiPochette:20200316003656j:plain unsplash-logoMarkus Spiske

PowerShell コマンドは、以下の 3 種類に分類される。

  • エイリアス (Alias)
  • 関数 (Function)
  • コマンドレット (Cmdlet)

本記事では、それぞれの実装の調査方法を説明する。

エイリアス (Alias) を調べる

PowerShell にはエイリアス (alias) と呼ばれる短縮コマンドが用意されている。
たとえば "cd"、"dir" や "rm" といったコマンドプロンプト風のコマンドは、このエイリアスで実現されている。

エイリアスの一覧を取得するには、以下のコマンドを実行する。

Get-Alias

特定のエイリアスがどのコマンドに割り当てられているのかを知るには、以下のようにコマンドを実行する。

Get-Alias <alias>
# (例) Get-Alias ls

関数 (Function) を調べる

PowerShell の関数は PowerShell で実装されており、次のコマンドで実装内容を確認できる。

(Get-Command <function>).Definition
# (例) (Get-Command Update-Script).Definition

コマンドレット (Cmdlet) を調べる

PowerShell のコマンドレットは、.NET Framework で実装されている。
このため、まずはどの DLL ファイルに、どのような完全名で実装されているのかを確認する必要がある。

コマンドレットの詳細を取得するには、以下のコマンドを実行する。

Get-Command <Cmdlet> | Format-List *
# (例) Get-Command Get-WinSystemLocale | Format-List *

出力例として "Get-WinSystemLocale" の例を示す。

HelpUri             : https://go.microsoft.com/fwlink/?LinkID=242247
DLL                 : C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.InternationalSettings.Commands\v4.0_3.0.0.0_
                      _31bf3856ad364e35\Microsoft.InternationalSettings.Commands.dll
Verb                : Get
Noun                : WinSystemLocale
HelpFile            : Microsoft.InternationalSettings.Commands.dll-Help.xml
PSSnapIn            :
Version             : 2.0.0.0
ImplementingType    : Microsoft.InternationalSettings.Commands.GetWinSystemLocaleCommand
Definition          :
                      Get-WinSystemLocale [<CommonParameters>]

DefaultParameterSet :
OutputType          : {}
Options             : ReadOnly
Name                : Get-WinSystemLocale
CommandType         : Cmdlet
Source              : International
Visibility          : Public
ModuleName          : International
Module              : International
RemotingCapability  : PowerShell
Parameters          : {[Verbose, System.Management.Automation.ParameterMetadata], [Debug,
                      System.Management.Automation.ParameterMetadata], [ErrorAction,
                      System.Management.Automation.ParameterMetadata], [WarningAction,
                      System.Management.Automation.ParameterMetadata]...}
ParameterSets       : {[<CommonParameters>]}

注目するべきは、DLLImplementingType の 2 つ。
これにより、どこ (DLL が示すパス) に、どのような完全名 (ImplementingType) で実装されているのかが分かる。

.NET デコンパイラを使う

DLL ファイル内の実装を調べるには .NET デコンパイラと呼ばれるツールを使用する必要がある。
.NET デコンパイラについては、著名なツールを別の記事でまとめているので、そちらを参照してほしい。

azukipochette.hatenablog.com