Code for final

ふぁいなる向けのコード置き場です。すでにコードじゃないこともいっぱい。

Windowsのネットワークと共有センターのトラブルシューティングでも復帰しない場合に、ネットワークを初期化するコマンドを実行したら直った話。

先日、会社で使用していたPCが突然、ネットワークに繋がらなくなりました。
前日まで使えてたので設定が悪いわけでもありません。
そして周りの席のメンバーは普通に使えているのでネットワーク障害でもないです。

ネットワークトラブルのときよくやるのが、ネットワークと共有センターのトラブルシューティングですが、 それでも問題を特定できないと言われる。
顧客から借りているPCなので使えないと仕事にならないし、交換を依頼してもすぐもらえるかわからないし、 何よりレビューをする必要があるものがたまっている。
詰んだ。。

とりあえず状況を確認した。

設定を確認した

設定が飛んだ可能性を疑って、ipconfigをたたいたらipアドレスdnsが表示されたので設定は問題なかった。

ケーブルを交換した

隣のメンバーのケーブルを借りてやってみるもつながらず。

IPアドレスを交換した

さらに隣のメンバーのIPを借りてやってみるもつながらず。

バイスマネージャからネットワークドライバを削除して再インストールした

設定が消えて再設定するはめになったが、つながらず。

隣のメンバーの端末にpingを飛ばした

宛先ホストに到達できませんというエラーで到達できず。

デフォルトゲートウェイpingを飛ばした

宛先ホストに到達できませんというエラーで到達できず。

ここでデフォルトゲートウェイpingを飛ばした結果を見て気づきました。
pingコマンドの最後に表示される損失が正常なら0%ですが、25%だったり、50%だったり 実行するたびに変わってました。
こんな現象ははじめてでした。

藁をもすがる想いで事象に関連しそうなものをググったがピンポイントな 解決方法は見つからず。 海外のページにネットワークの初期化コマンドを実行すればよいと書いてあるようなところがあったので コマンドをひたすら実行してみた。
するとつながった。

最終的に成功したのは以下の手順です。

1. ネットワークを初期する以下のコマンドを2つ連続して実行する。

>netsh interface ip reset c:\reset.log
>netsh winsock reset

どちらも今まで使ったことが無いコマンドですが、ネットワークの設定をリセットしてくれるみたいです。
片方のコマンドだけではだめだったので注意。

2.再起動してipアドレスを設定し直す。

再起動後、ipアドレスの設定が消えている(dnsは残ってました)ので再設定するとなんと繋がりました。

というわけで、原因は全く不明ですが、ネットワークの復旧ができました!

デフォルトゲートウェイpingを飛ばしたとき、謎の損失が確認できるときは ひょっとしたらこの手順で解消できるかもです。 お試しください。

Chromeを更新したら新しいタブのよく使うサイトのサムネイルが表示されなくなったのを復活する方法。

先日、Chromeが自動更新されてUIが変わりました。
それは別によかったんですが、新しいタブのよく使うサイトがアイコン表示に変わってしまいました。
最初はあんまり関係ないかと思って使っていたのですが、意外とサムネイルがないと不便ということが。。
無意識的にたぶん文字を読まずに視覚的に判断してたんですね。

で、復活させる方法がないか、海外のサイトを探しまくったところありました。
以下の4つの操作を行うことで復活可能なので困っている方はお試しください。

アドレスバーに「chrome://flags」をいれてEnterキー

設定画面に飛びます。

検索ボックスに「Enable using the Google local NTP」を入れてEnabledに変更

なぜNTPが?とおもったらNew Tab Pageのことっぽいですね。
Default→Enabledにします。

f:id:finalstream:20180922094715p:plain

検索ボックスに「New Tab Page Material Design Icons」を入れてDisabledに変更

こっちだけでいけると思ったけどNTPのほうも変更する必要があります。
Default→Disabledにします。

f:id:finalstream:20180922094839p:plain

Chromeを再起動

特に設定を保存するボタンとかはないのでそのまま再起動で問題ないです。
右下に現れる「RELAUNCH NOW」ボタンをクリックで再起動されます。

これで復活したと思います。

Windows10上のVM(CentOS)にDockerをいれてどんなものか体感する手順。

Dockerについて前々から気になっていたのでWindows10にDockerをいれてどんなものなのか体感するまでの 手順を書きたいと思います。Window10でやってますが、別にVirtualBoxが入ればWindows10でなくても問題ないです。
はじめに書いておきますが、わりと簡単に体感できます。
Linuxとかに慣れているひとであれば1hourくらいで体感できるのではないでしょうか。

まず、基本的にDockerはLinux上で動作するものということなのでLinuxVMにいれます。
Windows版もあるみたいですがHyper-Vとか必要っぽいので。

Dockerとは?

Dockerに興味があるひとがこの記事にたどり着いていると思うので説明不要だと思いますが、簡単に言えば仮想サーバ構築ツールです。
VMと異なるのはサーバごとにOSのインストールは不要で、1つのサーバ上に複数のサーバの構築ができます。
構築したサーバはイメージ化して配布できるので誰がやっても同じ環境が構築できます。
また、各種サーバアプリのイメージが公開されており、コマンド1つで構築可能です。
僕はインフラ周りはあまりやらないのですが、テスト環境構築とかで使えるのではないでしょうか。

www.docker.com

Oracle VirtualBoxをインストール

VMはなんでもいいんですが、使い慣れているVirtualBoxをインストールします。
特に何も注意すべきところはないのでインストーラを次へ次へでOKです。

Oracle VM VirtualBox

CentOSをダウンロード

Linuxもなんでもいいんですが、RedHat系で人気のあるCentOS 7をダウンロードします。
以下のサイトからMininal ISOをダウンロードしてください。

Download CentOS

仮想マシンを作成

VirtualBoxを起動して、新規を選択し、名前にCentOSと入れるとOSが選択されます。
あとはそのまま次へ次へで仮想マシンを作成します。

作成した仮想マシンの設定でネットワークを"NAT"から"ブリッジアダプター"に変更します。
NATでもできなくないですが、ポートフォワードを設定するのがめんどいので。

f:id:finalstream:20180917004323p:plain

ブリッジにし忘れると以下のように運が悪いとドハマリします。

final.hateblo.jp

仮想マシンを起動してCentOSをインストール

起動したらダウンロードしたISOを指定して、Install CentOS 7を選択します。 あとはGUIなので次へ次へですが、ネットワークはONにしといたほうがよいかもです。
インストール中にrootのパスワードを設定します。
環境にもよりますが、インストールは10minくらいで終わると思います。
再起動してログインできればOKです。
ログインしたら以下のコマンドをたたいてipアドレスを確認します。 以下の例でいうと2:のinetの右横のがipアドレス(10.154.54.86)です。

[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:48:1e:42 brd ff:ff:ff:ff:ff:ff
    inet 10.154.54.86/24 brd 10.154.54.255 scope global noprefixroute dynamic enp0s3
       valid_lft 5420sec preferred_lft 5420sec
    inet6 fe80::b4fc:2848:14de:b0ca/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

RLoginをダウンロード

VirtualBoxだとカーソルが持ってかれて使いにくいのでWindowsからCentOSを操作できるように ターミナルソフトをいれます。なんでもいいですが、インストール不要で使いやすいRLoginを使います。
以下のサイトからダウンロードして任意の場所に解凍します。

rlogin/telnet/ssh(クライアント)ターミナルソフト

RLoginでCentOSに接続

RLogin.exeを起動します。
新規接続でsshを選択して、さきほど確認したipアドレスをいれます。 あとはユーザをroot、パスワードを決めたやつをいれてOKします。
初回接続の際にいろいろ聞かれますが、はいでOK。

Dockerをインストール

いよいよDockerです。RLoginの画面で以下のコマンドを流すだけでインストールされます。

[root@localhost ~]# yum install -y  docker

Dockerを起動

起動は以下のコマンドを実行するだけです。

[root@localhost ~]# systemctl start docker

起動しているか確認。active(running)になっていればOK。

[root@localhost ~]# systemctl status docker
● docker.service - Docker Application Container Engine
   Loaded: loaded (/usr/lib/systemd/system/docker.service; disabled; vendor preset: disabled)
   Active: active (running) since 月 2018-09-17 01:48:28 JST; 7s ago
     Docs: http://docs.docker.com
 Main PID: 10950 (dockerd-current)
   CGroup: /system.slice/docker.service
           ├─10950 /usr/bin/dockerd-current --add-runtime docker-runc=/usr/libexec/docker/docker-runc-current --default-runtime=docker-runc --exec-opt native.cgroupdriver=systemd --userland-proxy-pat...
           └─10954 /usr/bin/docker-containerd-current -l unix:///var/run/docker/libcontainerd/docker-containerd.sock --metrics-interval=0 --start-timeout 2m --state-dir /var/run/docker/libcontainerd/...

 917 01:48:26 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:26.886529003+09:00" level=info msg="libcontainerd: new containerd process, pid: 10954"
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.049257313+09:00" level=info msg="Graph migration to content-addressability took 0.00 seconds"
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.050844195+09:00" level=info msg="Loading containers: start."
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.070560827+09:00" level=info msg="Firewalld running: true"
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.282047259+09:00" level=info msg="Default bridge (docker0) is assigned with an IP address 172.17.0....IP address"
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.479554825+09:00" level=info msg="Loading containers: done."
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.523279502+09:00" level=info msg="Daemon has completed initialization"
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.523307835+09:00" level=info msg="Docker daemon" commit="6e3bb8e/1.13.1" graphdriver=overlay2 version=1.13.1
 917 01:48:28 localhost.localdomain systemd[1]: Started Docker Application Container Engine.
 917 01:48:28 localhost.localdomain dockerd-current[10950]: time="2018-09-17T01:48:28.538125695+09:00" level=info msg="API listen on /var/run/docker.sock"
Hint: Some lines were ellipsized, use -l to show in full.

DockerでWEBサーバを構築

上記までの手順ではDockerのエンジンだけインストールされているのでこっから本領発揮のとこです。
apache webサーバを構築してみます。 Dockerは各種アプリのイメージが公式的に公開されており、そのイメージをダウンロードしてローカルサーバで動かす仕組みとなってます。
どんなイメージがあるかは以下のサイトで確認できると思いますが、RedminePostgreSQL、Jenkinsなどわりとなんでもあります。

https://hub.docker.com/explore/

なので以下のコマンドを流すだけで、構築ができてしまいます。

[root@localhost ~]# docker run -d -p 80:80 --name httpd httpd

起動したかは以下のコマンドで、httpdがいればOKです。

[root@localhost ~]# docker ps
CONTAINER ID        IMAGE               COMMAND              CREATED             STATUS              PORTS                NAMES
3fc96caa505a        httpd               "httpd-foreground"   6 minutes ago       Up 6 minutes        0.0.0.0:80->80/tcp   httpd

WEBサーバの起動を確認

Windowsからブラウザを起動して、ipアドレスをアドレスバーにいれてたたくと さみしいapacheのサンプル画面がでれば起動しているということです。

f:id:finalstream:20180917020828p:plain

DockerをGUIで操作

dockerですが、CUIで操作するのは結構たいへんです。
GUIで操作するツールも用意されています。

これもDockerでいれちゃいます。

[root@localhost ~]# docker run -d -p 8080:8080 --name rancher-server rancher/server

途中でファイアウォールが有効になっているうまくうごかないところがあるので切っておきます。

[root@localhost ~]# systemctl stop firewalld

起動後、Windowsの画面のブラウザからipアドレス:8080でアクセスすると以下の画面が表示されればOKです。
スペックによりますが、起動は1~2minくらいかかります。

f:id:finalstream:20180917024544p:plain

デフォルトは英語ですが、右下のところで日本語に変更できます。
まず管理者メニューのアクセスコントロールでLOCALを選択し、管理者を登録します。

その次にインフラストラクチャでホストを選択します。
ホストを追加して保存します。

以下のコマンドをコピー&ペーストし実行しホストを登録します Rancher:と書いてあるのでコマンドをターミナルで流します。
こうすることでサーバとの紐づけ自動で行ってくれます。

# 内容は環境によって異なります。以下は私の環境での例です。
sudo docker run --rm --privileged -v /var/run/docker.sock:/var/run/docker.sock -v /var/lib/rancher:/var/lib/rancher rancher/agent:v1.2.11 http://10.154.54.86:8080/v1/scripts/06051ED6561D2F86C07A:1514678400000:UCPy9qbQ1dQ2KCue0CLu076A

あとはホストの画面で見れば、Dockerで動いているもの(コンテナ)が確認できます。

最後に

まだまだ奥が深いDockerですが、ここまでなんとなくDockerについて手軽な感じが伝わったかと思います。
僕もまだまだ勉強中ですが、素敵なDockerライフを。

VM(CentOS)からhttpsで接続をするとなぜかエラーになるとき。(ESETが入っている環境)

Dockerを勉強のために構築していたのですが、https系の接続がことごとくエラーとなってドハマリしたので記録しておきます。

Dockerで普通にpullをしました。

[root@localhost ~]# docker pull httpd
Using default tag: latest
Trying to pull repository docker.io/library/httpd ... 
Get https://registry-1.docker.io/v2/: x509: certificate signed by unknown authority

wgetでもだめです。

[root@localhost ~]# wget https://registry-1.docker.io/v2/
--2018-09-16 23:21:05--  https://registry-1.docker.io/v2/
registry-1.docker.io (registry-1.docker.io) をDNSに問いあわせています... 52.54.155.177, 34.233.151.211, 34.206.236.31, ...
registry-1.docker.io (registry-1.docker.io)|52.54.155.177|:443 に接続しています... 接続しました。
エラー: registry-1.docker.io の証明書(発行者: `/CN=ESET SSL Filter CA/O=ESET, spol. s r. o./C=SK')の検証に失敗しました:
  発行者の権限を検証できませんでした。
registry-1.docker.io に安全の確認をしないで接続するには、`--no-check-certificate' を使ってください。

調べて見ると同じように困っている人は多く、以下の2つの場合、エラーになる可能性があるようでした。

  • OSにバンドルされている証明証が古い。
# 以下のコマンドを流して最新化する
[root@localhost ~]# yum update openssl
  • 時刻がずれている。
# 以下のコマンドを流して同期をとる
[root@localhost ~]# ntpdate -bv ntp.nict.jp

OSを入れたばかりなのでどちらも問題ないはずと思いつつ、だめもとで試しましたが、だめでした。

次にSSLの動作を確認するコマンド(curl)で確認しました。

[root@localhost ~]# curl -v  https://registry-1.docker.io/v2/
* About to connect() to registry-1.docker.io port 443 (#0)
*   Trying 34.201.236.93...
* Connected to registry-1.docker.io (34.201.236.93) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* Server certificate:
*       subject: CN=*.docker.io
*       start date:  705 00:00:00 2018 GMT
*       expire date:  805 12:00:00 2019 GMT
*       common name: *.docker.io
*       issuer: C=SK,O="ESET, spol. s r. o.",CN=ESET SSL Filter CA
* NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER)
* Peer's Certificate issuer is not recognized.
* Closing connection 0
curl: (60) Peer's Certificate issuer is not recognized.
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

ではほかのサイトもどうなのかとgoogleで確認してみました。

[root@localhost ~]# curl -v  https://google.com/
* About to connect() to google.com port 443 (#0)
*   Trying 216.58.197.174...
* Connected to google.com (216.58.197.174) port 443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* Server certificate:
*       subject: CN=*.google.com,O=Google LLC,L=Mountain View,ST=California,C=US
*       start date:  828 18:23:00 2018 GMT
*       expire date: 1120 18:23:00 2018 GMT
*       common name: *.google.com
*       issuer: C=SK,O="ESET, spol. s r. o.",CN=ESET SSL Filter CA
* NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER)
* Peer's Certificate issuer is not recognized.
* Closing connection 0
curl: (60) Peer's Certificate issuer is not recognized.
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

ん?よくよく見比べて見ると気になるものが。。
どっちも発行者(issuer)がESETではありませんか!
ESETが認証局サービスを始めたにしても偶然すぎるし、Filterってのが怪しすぎる。

で、さっそくESETの設定を確認。
ありました。怪しそうな設定が…"SSL/TLSプロトコルフィルタリング"がONになってます。
f:id:finalstream:20180916230813p:plain

試しにOFFにするとすんなり通りました。

[root@localhost ~]# docker pull httpd
Using default tag: latest
Trying to pull repository docker.io/library/httpd ... 
latest: Pulling from docker.io/library/httpd
Digest: sha256:8631904c6e92918b6c7dd82b72512714e7fbc3f1a1ace2de17cb2746c401b8fb
Status: Image is up to date for docker.io/httpd:latest

みなさんもESET入れている方で、SSL/TLS系の通信がおかしいときとは"SSL/TLSプロトコルフィルタリング"の設定を確認しましょう。

ちなみになぜゲスト(CentOS 7)でホスト(Windows10)にインストールされているESETの影響を受けているか気になったので調べると 案の定、VMのネットワーク設定がNAT接続になっていました。ブリッジにすると影響をうけなくなったので、 最終的には"SSL/TLSプロトコルフィルタリング"をOFFにするのではなく、VMのネットワーク設定をブリッジ接続にするという対応にしました。

Firefoxをアップデートしてから動作がおかしくなった場合はFirefoxのリフレッシュを。※代償あり

Firefox 60にアップデートしてから突然、新しいタブページがブランクになってしまいました。 アップデート前は最近表示したサイトや検索ボックスなど表示されており、便利でした。

support.mozilla.org

ヘルプを見てみましたが、

他のページをホームページに設定していない限り、新しい は、既定 の Firefox スタートページでもあります。

となんやらおかしい日本語で記載されており、設定を確認しましたが、初期値のままでした。

初期設定に戻すボタンも押してみましたが、変わらず。

さらにヘルプを見るとリフレッシュという機能があるみたいです。 これを実行すると、なんと新しいタブページが復活しました!

support.mozilla.org

ですが、これには代償がありました。
なんかアドレスバーの横がめっちゃスッキリしています。
よくヘルプを確認すると拡張機能とテーマが消えます』と記載されていました。
あとの祭りですが何をインストールしていたのか覚えてません。。

メッセージで教えてくれてもいいのに。Mozillaさん。。
まー必要になったときに足りないことに気づくでしょう。
と思っていましたが、しばらくしたら同期されてもとに戻ってました。
Firefox Syncを設定しておいて助かりました。

ご親切なことに新しいタブもブランクに戻っています。。
振り出しに戻りました。
問題は拡張機能かテーマってことがわかったのですが、全部無効にしても治らなかったです。
まーそのうちアップデートで解消されると思うのでしばらく放って置くことにします。
ちなみに新しいタブはアドレスバーに『about:home』って入力したら表示されます。
なので原因不明です。(時間があるときに調べて判明したら更新します)

Firefoxをアップデートして、動作がおかしくなった場合は、プロファイルのバックアップをとってからリフレッシュをお試しください。

バックアップ方法は以下を参照ください。

support.mozilla.org

Xamarin.Forms + Prismで空プロジェクトをビルドしただけなのに「"ResolveLibraryProjectImports" タスクが予期せずに失敗しました。」

ついこないだまでXamarin.Froms + Prismのプロジェクトが作成できていましたが、
いつからかビルドするとエラーになるようになりました。

前回失敗したファイルパスの問題ではないはずです。短くなるようにしたので。 final.hateblo.jp

f:id:finalstream:20171125205509p:plain

エラー一覧の下の方に以下のようなエラーが…。

The current .NET SDK does not support targeting .NET Standard 2.0.  Either target .NET Standard 1.6 or lower, or use a version of the .NET SDK that supports .NET Standard 2.0.

なんか足りないのかーということで、
以下のリンク先で『.NET Core SDK 2.0.x』をダウンロードしてインストール。

www.microsoft.com

インストール後、VisualStudioをあげなおして、ビルドしたところ成功しました!

原因は謎ですが、VisualStudioかXamarinかPrismを更新したときにデフォルトのターゲットフレームワークが変わったんだと思います。

Xamarin.FormsでSnackbarを表示する方法。

Xamarin.FormsでToastを表示する方法を調べていたらいたのですが、いまはToastではなく、Snackbarの時代なんですね。

ということでXamarin.FormsでSnackbarを表示する方法です。

Xamarinの場合、以下のプラグインをいれると簡単に表示できますのでありがたく使用させていただきましょう。

github.com

nugetでインストールできます。
"Toasts.Forms.Plugin"でソリューション内の全部のプロジェクトにインストールします。

僕はAndroidしか持っていないのでここからはAndroidオンリーなコードしか記載しませんが、上記のプラグインはXamarinなのでマルチプラットフォーム対応してます。

まず、ActivityのOnCreateにコードをたします。

        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.tabs;
            ToolbarResource = Resource.Layout.toolbar;

            base.OnCreate(bundle);

// ここから
            DependencyService.Register<ToastNotification>(); 
            var platformOptions = new PlatformOptions();
            platformOptions.Style = NotificationStyle.Snackbar;
            ToastNotification.Init(this, platformOptions);
// ここまで

            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App(new AndroidInitializer(this)));
        }

ポイントはPlatformOptionsでスタイルを指定することです 。
Snackbarと指定しないと通知になります。
これがどこにも書いてなくてソースをおっかけました。

逆に言えばこのプラグインを使用することで、通知も簡単に投げれるということですが。

次に共通ロジック(PCL)の呼び出すところです。
今回のコードは接続が成功したらSnackbarを表示するコードです。

            LeonetConnecter.Connected += async (sender, args) =>
            {
                var notificator = DependencyService.Get<IToastNotificator>();
                var androidOptions = new AndroidOptions();
                androidOptions.DismissText = "";

                var options = new NotificationOptions()
                {
                    Title = "Success",
                    AndroidOptions = androidOptions
                };

                await notificator.Notify(options);
            };

これだけで以下のように表示できます。

f:id:finalstream:20171119184549p:plain

ちなみにスナックバーはトーストと違ってアクションを受け取ることができます。
DismissTextを設定することでアクションボタンができます。

f:id:finalstream:20171119185422p:plain

Notifyメソッドの戻り値でボタンが押されたかわかりますので、簡単ですね。