xin9le.net

Microsoft の製品/技術が大好きな Microsoft MVP な管理人の技術ブログです。

タスクバーのアイコン表示が壊れたときの対処方法

Windows 10 を使っていると、タスクバーに表示される Microsoft Edge などの UWP 関連アプリのアイコンの表示がおかしくなるときがあります。以下の画像で言うところの、Edge とか Store のアイコンみたいな感じです。今回はこれにハマったのでメモ。

f:id:xin9le:20160712204131p:plain

原因と解決方法

こうなる原因としては、アイコンのキャッシュが良くない形で生成されているためです。なんでそんな不正なキャッシュができるのかは分かりませんが、SageThumbs などを使っていると発生しやすいようです。とは言え、キャッシュを消してやれば直ります。悪さをしてると思われるアイコンキャッシュは以下。

  • %LOCALAPPDATA%\IconCache.db
  • %LOCALAPPDATA%\Microsoft\Windows\Explorer\iconcache_*.db
  • %LOCALAPPDATA%\Microsoft\Windows\Explorer\thumbcache_*.db

エクスプローラーがこれらのキャッシュファイルを握ってしまっていて消せなかったりするので、削除する際はエクスプローラーを強制終了してやる必要があります。

削除コマンド

ということで削除するためのコマンドを用意しました。以下のコードを RemoveIconCache.cmd などとして保存し、実行してください。

@echo off

rem //--- エクスプローラーを終了
taskkill /f /im explorer.exe

rem //--- 削除確認
echo アイコンキャッシュ消しちゃっうけどいいかなー?(いいともー
pause

rem //--- 削除
del /q /f %LOCALAPPDATA%\IconCache.db
del /q /f %LOCALAPPDATA%\Microsoft\Windows\Explorer\iconcache_*.db
del /q /f %LOCALAPPDATA%\Microsoft\Windows\Explorer\thumbcache_*.db

rem //--- エクスプローラー再開
explorer.exe
exit

簡単ですね!これでもうアイコンキャッシュの破損に悩まされないハズ!

変数宣言式

約一か月前に C# 7 の新機能についてライブコーディングをしたと思ったら、もうその情報だけでは足りていなくて焦っている今日この頃。

あれから Roslyn のリポジトリ には大きな変化がありました。

  1. future ブランチが master ブランチにマージされた!
  2. いくつかの新機能がさらに追加されている!

もはや毎日進捗を見てないとダメじゃないかと思うくらい、開発の速さに驚いています。最近新たに追加された新機能について実際に動かしてみたものベースで紹介して行きます。

out var

C# 6 のときに一度導入が検討されたけど見送りになった機能、変数宣言式が帰ってきました!前バージョンでの紹介の名残で変数宣言式と書いていますが、英語では「Out Variable Declarations」と呼ばれています。「返り変数宣言」とか訳したりするのかな...(知らんけど

どんな機能なのかは C# 6 のときに書いたものとほぼ同じなので、以下の記事をご参照くださいw (手抜き

簡単に概略を説明すると以下のような感じです。

//--- これまでのこんなコードを...
static void Main()
{
    int value;  //--- イチイチ前に変数を宣言
    if (int.TryParse("123", out value))
        Console.WriteLine(value);
}

//--- こう書けるようになる!
static void Main()
{
    if (int.TryParse("123", out var value))  //--- 式の途中で変数を宣言して
        Console.WriteLine(value);            //--- それを利用する
}

必須じゃないけど地味に嬉しい、そんな機能かなと思います。

C# 6 で検討されていた仕様との差分

C# 6 のときは out 宣言した変数の寿命は、宣言したステートメントのスコープに限られました。C# 7 ではそのスコープに限定せず、通常の out 変数の利用と同じスコープで変数が有効になりました

//--- C# 6 の頃に検討されていた仕様
static void Main()
{
    if (int.TryParse("123", out var value))
    {
        //--- このスコープでしか value 変数を使えない
        Console.WriteLine(value);
    }
}

//--- C# 7 ではこうなる
static void Main()
{
    if (int.TryParse("123", out var value))
    {
        //--- このスコープでも当然使えるし
        Console.WriteLine(value);
    }

    //--- ここでも使える
    Console.WriteLine(value);    
}

なので、同一変数名で何度も TryParse な if 文を並べるようなことはできなくなりますが、これまでの out 変数と同じ挙動を優先したのだと推測します。

LINQ 大好き C#er がアイドルグループ LinQ のセットリスト考えてみた

C#er といえば LINQ が大好き!もちろん LinQ も大好き!?

f:id:xin9le:20160628015532p:plain

昔は TwitterLINQ と呟けば LinQ のメンバーさんにフォローされたり Fav されたりしたものでした。その頃から「せっかく LinQ なんて超素敵な名前だったら LINQ を題材にしたアルバムでも作ればいいのに」なんて思っていました。

数年経ってふとそんなことを思い出したので、気分転換に考えてみました。すべてネタなので真に受けないでください。

恋の Query - あなたとわたしのメソッドチェイン -

  1. from in 九州
  2. GroupBy Kawaii Girls
  3. Join ファンクラブ
  4. ありがとう fans.First();
  5. Select - i なんか要らない -
  6. OrderBy イケメン
  7. Distinct 量産型
  8. Where().Where().Where() - 王子様探し -
  9. 私のファンを SelectMany
  10. foreach 握手会
  11. Take(7) - 神セブン -
  12. 忘れないで Reset
  13. members.Count() == 29;
  14. Union HKT48
  15. お願い、何度も舐めないで
  16. 迷うわ、Any なの? All なの?どっちが好きなの?
  17. yield break; - きっとまた後で -
  18. セピア色の IQueryable
  19. Single - 私だけにして -
  20. Except - 卒業 -
  21. Finally...

C# 7 をライブコーディングで解説してきました

f:id:xin9le:20160522222757p:plain

ここまで数回に渡って C# 7 の新機能について解説してきました。記事は以下にまとめてありますので是非ご覧ください。

と、そんなこんなまとめていたのを「C# ユーザー会 //build/ 2016 振り返り勉強会」で解説してきました。当日の朝にクローンしてきたばっかりのコードからビルドしたコンパイラを使って、ライブコーディング中心でお届け!実際に動かして説明するのが一番分かりやすいですよね、やっぱり!

セッション資料

セッション資料はライブコーディングによるデモのおさらいという形で簡単にまとめてあります。

これまで数年タイトルスライドが同じだったのですが、いい加減に飽きていたのでちょっとだけ綺麗に作ってみました。//build/ の振り返りということで、//build/ のサイト背景を使ってみました。ちょっとした遊び心でしたが、気付いた方いたかな?w

みなさんの反応

結構な方が見に来てくださっていたので、お察しの通り (?) 実は結構緊張していました。最前列には MVP 達がシッカリ陣取り、後ろの方では岩永先生 (@ufcpp) に見られている...。隅から隅まで圧力のカタマリでライブコーディングしているときに若干指が震えていました!(ほんとに

頷きながら聞いてくれる方、「おぉ!」と驚いた表情を見せる方、バシバシ写真を撮ってくださる方、いろんな反応が見えました。セッション関連のツイートを追いかけてみても、みなさん結構反応してくださっていましたね!特に @chomado さんは写真付きでバンバン投稿してくださっていて、大変ありがたかったです :)

ちょまどさんと言えば今回初めてお会いしたのですが、セッション後に「すごく良かったです!」とすぐに言いに来てくださいました。そういう反応は本当に嬉しいですねー。1 か月以上準備してきてよかった!懇親会での感想やアンケート結果にも「ライブコーディングがとても良かった」系の反応が結構あって、とても自信になります。今後もライブコーディングマンとして頑張ろうかなw

「C# vNext」でググれ!

なんと今なら「C# vNext」でググるとこのサイトがトップに表示されますw

というのをイベント前日に知って最後にネタでブッ込んでみました。岩永さんの「C# でググれ」を真似して「C# vNext でググれ!」、ということで今後ともよろしくお願いします!

型スイッチ

F# などの関数型言語をやっている方にはおなじみのパターンマッチング。「10 年おせーよ!」と言われそうですが、C# 7 にもそんな待ちに待った (?) 機能が搭載されそうです。主に既存の is キーワードと switch キーワードを拡張した、型に対するマッチングになる見込みです。本家ではこの機能を Type Switch と呼んでいるようです。パターンマッチングについては以下にまとめられています。

全体計画の一部を実装

パターンマッチングとしては他にも match 式や let ステートメントなども検討されていますが、それらは C# 8 以降での追加になりそうです。詳細は以下を参照してください。

f:id:xin9le:20160513032103p:plain

is 拡張

C# 6 までの is キーワードは以下のように型判定に使われていました。

if (x is string)
{
    //--- 変数 x が string 型だった場合の処理
}

このように is の後ろに型を指定して判定するだけの機能でしたが、これが大幅に拡張されます。

定数マッチング

特定の値かどうかを判定できるようになります。等価演算子 (==) で良いのではないか?と思えるくらいには存在意義を見出せない...。

//--- 何か値があるとする
var x = 123;

//--- C# 6 まではこんな感じ
var a = x == 123;  //--- True
var b = x == 456;  //--- False
var c = x == 'a';  //--- False

//--- C# 7 ではこんな感じで判定できるように!
var a = x is 123;   //--- True
var b = x is 456;   //--- False
var c = x is 'a';   //--- False
var d = x is "123"; //--- Error!! : Cannot implicitly convert type 'string' to 'int'

型マッチング

特定の型かどうかの判定ができるようになります。...と言うと「それ今までと同じやん!」と思われるかもしれませんが、特定の型判定に加えて変数の生成を同時にやってくれます。以下のサンプルを見てください。

//--- 何か object 型に入った値があるとする
object x = "abc";

//--- C# 6 ではこう
var v = x as string;
if (v != null)
{
    //--- 変数 v に対する処理
}

//--- もしくはこう
if (x is string)
{
    var v = (string)x;
    //--- 変数 v に対する処理
}

//--- C# 7 からはこう書ける!
if (x is string v)
{
    //--- 変数 v に対する処理
}

見慣れない書き方に若干戸惑うかもしれませんが、以下のような動きをしています。

  1. xstring 型かどうかを判定
  2. string 型だった場合、string 型の変数 v に値を代入
  3. 評価結果を bool 型で返す

型マッチングの変数スコープ

先の変数 v のスコープは if 文のスコープのみです。なので、以下のように変数として評価結果を受ける場合は v にアクセスできません

object x = 123;
var r = x is string v;
Console.WriteLine(r);  //--- false
Console.WriteLine(v);  //--- 変数 v を参照できないのでコンパイルエラー!

型マッチングが便利なシーン

以下のような null 許容型の判定などで便利そうです。だいぶスッキリと書ける印象があります。

//--- C# 6 ではこう
int? v = x?.y?.z;
if (v.HasValue)
{
    var v = x.GetValueOrDefault();
    //--- v を使った何か
}

//--- C# 7 ではこう書ける!
//--- null のときの評価は当然 false
if (x?.y?.z is int v)
{
    //--- v を使った何か
}

型マッチングの型判定は厳密

これまでの is キーワードと同様、型マッチングの型判定は非常に厳密です。ですので暗黙的型変換などは期待してはいけません。

object x = 123;

Console.WriteLine(x is int);  //--- true
Console.WriteLine(x is long); //--- false

if (x is int  v1){ /* OK */ }
if (x is long v2){ /* NG */ }  //--- 暗黙的型変換は当然してくれません

逆コンパイル

is 式の判定がどのように行われているか、ILSpy で逆コンパイルして覗いてみましょう。以下のように展開されます。

//--- これを逆コンパイルにかけると...
static void Main()
{
    object x = "abc";
    if (x is string v1) Console.WriteLine(v1);
    if (x is int v2)    Console.WriteLine(v2);
}

//--- こう展開される
static void Main()
{
    object x = "abc";

    //--- 参照型の場合はそのまま as で判定
    string v1 = x as string;
    bool flag = v1 != null;
    if (flag)
        Console.WriteLine(v1);

    //--- 値型の場合は null 許容型として判定
    int? num = x as int?;
    int v2 = num.GetValueOrDefault();  //--- if 文の中で展開すればいいのでは?(と思ったり
    bool hasValue = num.HasValue;
    if (hasValue)
        Console.WriteLine(v2);
}

参照型かどうかの判定の場合はただの as キーワードで、値型かどうかの判定の場合は as キーワード + null 許容型で行われるみたいですね。

switch 拡張

is キーワードが拡張されたのと同様の機能が switch 文としても組み込まれます。書き方がちょっと変わっただけなので、is の書き方が分かれば難しくないですね!

object x = 123;
switch (x)
{
    case "abc":
        Console.WriteLine(x);
        break;

    case int v:
        Console.WriteLine(v);
        break;
   
    default:
        Console.WriteLine("default");
        break;
}

when 句による条件設定 (case guard)

C# 6 では 例外フィルター という catch 句の後ろに when 句を付ける条件分岐機能が追加されました。これと似た感じで、case 句の後ろに when 句を入れて条件分岐する「case guard」と呼ばれる機能が追加されます。以下のように使います。

object x = 123;
switch (x)
{
    case "abc":
        Console.WriteLine(x);
        break;

    case int v when 100 < v:  //--- v が 100 より大きいとき
        Console.WriteLine(v);
        break;

    case int v:  //--- v が 100 以下のとき
        Console.WriteLine(v);
        break;
   
    default:
        Console.WriteLine("default");
        break;
}

これでより細かい条件分岐を簡潔に書くことができるようになりましたね!

逆コンパイル

switch 文も逆コンパイルして展開結果を確認してみましょう。上のコードを展開すると以下のようになります。

object x = 123;
object obj = x;  //--- どーにも納得できないけど一度コピーが入ってる...
if (object.Equals(obj, "abc"))
{
    Console.WriteLine(x);
}
else
{
    int? num = obj as int?;
    int v = num.GetValueOrDefault();
    if (num.HasValue && 100 < v)  //--- when 句で指定した条件も入っている
    {
        Console.WriteLine(v);
    }
    else
    {
        num = (obj as int?);
        int v2 = num.GetValueOrDefault();  //--- これも if の中で展開して欲しい
        if (num.HasValue)
        {
            Console.WriteLine(v2);
        }
        else
        {
            Console.WriteLine("default");
        }
    }
}

if 文を使って上手くやっている感じですね。