azukipochette's weblog

memory dump (mini)

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

2020 年版 .NET デコンパイラまとめ

f:id:AzukiPochette:20200316003028j:plain unsplash-logoRyan Quintal

.NET Reflector

著名な RedGate 製 .NET デコンパイラ。有料 ($100)。
かつて無料だったが、有償化すると発表したことで各社が無料のデコンパイラを公開したという過去がある。JustDecompiler が "永久無料" と謳っているのはこうした歴史背景に基づく。
拡張性が高く、複数の言語や言語バージョンに変換することができる。Visual Studio と連携できる VSPro 版もある。

www.red-gate.com

無料だった頃にコミュニティによって様々な便利アドインが開発されており、寿命短い CodePlex 上にまとまっている。
この中には PowerShell に変換するためのアドインも含まれている。

archive.codeplex.com

ILSpy

著名な .NET デコンパイラ。無料。
最新バージョンでは、.NET Reflector の長所であった特定言語バージョンへの変換にも対応している (C# のみ)。

github.com

JustDecompile

Telerik 製の .NET デコンパイラ。永久無料を謳っている。

www.telerik.com

デコンパイル エンジンは GitHub でコードが公開されている。

github.com

dotPeek

IntelliJ IDEA や ReSharper を開発している JetBrains 製の .NET デコンパイラ (無料)。
WinDbg などを使ってデバッグする人には、シンボル サーバーにもなる機能が非常に便利。

www.jetbrains.com

dnSpy

話題の .NET デコンパイラ。
Visaul Studio 風の UI を持ち、C#, Visual Basic, IL に変換できる。
無料で使用する事ができる (寄付も可)。

github.com

Enterprise Architect の動作解析の設定を Visual Studio のバージョン・エディションに依存させない方法

f:id:AzukiPochette:20200315224327j:plain

unsplash-logoSneaky Elbow

調べてみると約 7 年ぶりの Enterprise Architect の記事です。大変久しぶりですが、内容は短めです。

Enterprise Architect にはコードを分析してモデルを自動生成することができる大変素晴らしい機能が搭載されています。
Visual Studio ソリューションを読み込むことで、動作解析の設定も自動的に設定してくれるのですが、残念ながら Visual Studio 2017 以降では正しく動作しないケースがあります。

原因と背景

この問題は、Visual Studio 2017 以降から複数のバージョンだけでなく、エディションも共存できるようになったことに起因しています。
複数のバージョンとエディションを共存できるようにするため、Visual Studio 2017 以降では次のようにフォルダ構造が見直されました。

C:\Program Files (x86)\Microsoft Visual Studio\<Version>\<Editoin>

このため、devenv.exe をコマンドラインで実行するためには、そのバージョンだけでなくエディションも知らなければ、パスを判断することができないのです。

解決策

個人で使うのであれば特定のバージョンとエディションで固定しまうのも1つの方法ですが、環境によって Visual Studio のバージョンやエディションが異なる場合は、動作解析の設定を環境に合わせて都度変更する必要があります。
これが面倒という方にオススメなのが、Visual Studio Locator (VSWhere) を利用する方法です。

Visual Studio Locator は、その名の通り Visual Studio がどこに保存されているのかを教えてくれる便利なコマンドライン ツールです。
Visual Studio 2017 (15.2) 以降では標準で搭載されており、絶対パスは %ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe と決まっています。

というわけで、Enterprise Architect の動作解析の設定を以下のようにしておけば、devenv.com の完全パスを自動的に見つけてくれるようになります。*1

CD "path/to/your project folder"
FOR /F "usebackq delims==" %%X IN (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -find \**\devenv.com`) DO SET DEVENVCOM="%%X"
%DEVENVCOM% "<your solution>.sln" /build "Debug|Any CPU"

素敵ですね。

おまけ

Visual Studio Locator に興味がある方は、GitHub でコードが公開されていますので、そちらをご確認ください。

github.com

それでは、よい Enterprise Arctehict 生活を。Enjoy!

*1:Visual Studio 2017 以前のバージョンには対応していません。また、例では最新バージョンを使用するように設定していますが、特定のバージョンを見つけたい場合は -latest の代わりに -version オプションを使用してください