Quantcast
Channel: 蒼の王座・裏口
Viewing all 183 articles
Browse latest View live

Windows 8.1で、VirtualBoxとHyper-Vを簡単に切り替える方法

$
0
0

Hyper-VとVirtualBoxは同時に使用することができない。
Hyper-Vを使用してる状態でVirtualBoxを使用するには、機能の追加/削除でHyper-Vをオフにすることで使用できるようになる。

でも、それだと大がかりで面倒だよねー。だから管理者コマンドプロンプトで対応しちゃおう。ブートメニューに[No Hyper-V]を用意する。
最初のコマンドでGUIDを取得して、そのGUIDを使って2つ目のコマンドを実行する。

C:\>bcdedit /copy {current} /d "No Hyper-V"
The entry was successfully copied to {ff-23-113-824e-5c5144ea}.

C:\>bcdedit /set {ff-23-113-824e-5c5144ea} hypervisorlaunchtype off
The operation completed successfully.

これ重要!
Windows 8.xでは、WindowsはFASTスタートアップに最適化されてる。
なんで起動が早すぎて、ブート選択がしにくい!
Shiftを押しつづけながら、再起動をクリックしよう。

image

そーすると、起動時に次のような画面がでてくるので、ほかのOSを選択する。で、No Hyper-Vを選択すればOK!

Windows 8.1 Boot Menu

Selecting No Hyper-V

 

元記事は、Switch easily between VirtualBox and Hyper-V with a BCDEdit boot Entry in Windows 8.1


VagrantでHyper-Vやるぜ!

$
0
0

VagrantがサポートしているHyper-Vは、Windows 8.1のみ。
以前のバージョンのHyper-VのAPIに対応していなくて、動作しないことがあるらしい。

Hyper-VとVirtualBox、VMwareなどの仮想化技術は共存ができない。Hyper-Vが有効になっているとVirutualBoxでエラーが出るので、Hyper-Vを無効化する必要がある。具体的には、[Windows 8.1で、VirtualBoxとHyper-Vを簡単に切り替える方法]を参照。

Hyper-Vを使用するには、予めWindowsの機能追加と削除でHyper-Vを有効にしておく必要がある。
image

 

Hyper-Vを使用するには、[vagrant up]コマンドのオプション[—provider]に[hyperv]を指定する。実行するときには、管理者特権が必要で、権限がない場合、Vagrantはエラーを返す。

image

The Hyper-V provider requires that Vagrant be run with
administrative privileges. This is a limitation of Hyper-V itself.
Hyper-V requires administrative privileges for management
commands. Please restart your console with administrative
privileges and try again.

 

コマンドプロンプトを意気揚々と管理者特権で起動してコマンド実行!

vagrant init hashicorp/precise64
vagrant up –provider=hyperv

また、エラー・・・。

image

There are no virtual switches created for Hyper-V! Please open
the Hyper-V Manager, go to the "Virtual Switch Manager", and create
at least one virtual switch.
A virtual switch is required for Vagrant to create a Hyper-V
machine that is connected to a network so it can access it.

Hyper-V用の仮想スイッチが作成されていないので、Hyper-Vマネジャーで仮想スイッチマネージャーから仮想スイッチを作成してね!っとのこと。
てなわけで、仮想スイッチを作成しちゃいましょう!

image

仮想スイッチを作成したら、改めて[Vagrant up]

vagrant up –provider=hyperv

image

SMBフィル共有で何かエラーがでているが、もう疲れたよ、ママン。
なので、エラーはでてるが気にしない。
気にしなければ、Hyper-Vでの操作はおしまい。

SMB同期

デフォルトでは、SMB同期が有効になっている。
SMB同期は、ネットワーク共有設定をするが、[vagrant destroy]などでネットワーク共有をクリーンアップしないので残り続けるので、必要に応じて自分で解除する必要がある。

image

 

制限事項

Vagrantは、まだHyper-V用の新しいネットワーク設定と作成方法を把握していません。
Hyper-Vでマシーンを起動するとき、Vagrantはどの仮想スイッチに仮想マシンを接続したいかを確認します。

Vagarantは、固定IP設定や自動NAT設定をすることはできません。

Vagrant upの過程で、マシンの仮想IPを報告し、ホストオンリーのネットワークでIPアドレスを使用できます。

 

vagrant up –provider=hyperv でエラー

c:\work\ubuntu>vagrant up –provider=hyperv
Bringing machine ‘default’ up with ‘hyperv’ provider…
==> default: Importing a Hyper-V instance
    default: Cloning virtual hard drive…
    default: Creating and registering the VM…
C:/HashiCorp/Vagrant/embedded/gems/gems/childprocess-0.5.1/lib/childprocess/abstract_process.rb:183:in `assert_started’:
process not started (ChildProcess::Error)
        from C:/HashiCorp/Vagrant/embedded/gems/gems/childprocess-0.5.1/lib/childprocess/windows/process.rb:39:in `exite
d?’
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.0/lib/vagrant/util/subprocess.rb:207:in `ensure in exec
ute’
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.0/lib/vagrant/util/subprocess.rb:209:in `execute’
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.0/lib/vagrant/util/subprocess.rb:22:in `execute’
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.0/lib/vagrant/util/powershell.rb:32:in `execute’
        from C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-1.5.0/plugins/providers/hyperv/driver.rb:96:in `execute_pow
ershell’

こんな感じで、エラーが出ると途方にくれますね。
[SET VAGRANT_LOG=debug]で詳細ログを見ると、原因がわかるかも。

ちなみに今回のケースでは、仮想スイッチ名に日本語を使用していたらから、文字化けしちゃって使用できなかったから。仮想スイッチ名を[新しい仮想スイッチ]からアルファベット(たとえば[out]とか)にしたら正常に動作した。

知っても得はしないけど、しりたいよね?vagrant shareの裏側の仕組み

$
0
0

image

1.vagrant share

仮想マシンのNW状況を確認します。
IPやポートフォワードの状況などを確認して、設定すべき情報をチェックします。

2.プロキシサーバーの登録と共有URLの発行 register.vagrantshare.com

https://register.vagrantshare.com のRest APIにリクエストを投げます。
リクエストを受け取ると、プロキシサーバーが生成されます。
プロキシサーバーが生成されたら、レスポンスが返ってきます。
レスポンスには、プロキシサーバーの名前と有効期限、ポート番号が含まれています。

3.ホストOSでプロキシソフトを起動

プロキシサーバーと通信をするために、プロキシを起動します。
Windowsの場合は、

C:/HashiCorp/Vagrant/embedded/gems/gems/vagrant-share-1.0.0/localbin/proxy_windows_386.exe
を起動します。
起動オプションに、プロキシサーバー名やポート番号がわたされます。
内側から外側に向けた通信でトンネル作成ですね。

4.プロキシソフトからプロキシサーバーに接続

プロキシソフトから、プロキシサーバー(register.vagrantshare.com:8000)に接続して、通信を確立します。

5.インターネット上から接続します

これでインターネット中からアクセスできるようになりました。
http://bored-lovebird-5488.vagrantshare.com
にアクセスすると、プロキシサーバーにアクセスし、プロキシサーバー経由でホストOS、ホストOSからゲストOSに接続します。

あら、素敵。

大きなテーブルからランダムに行を取得する方法

$
0
0

ちょっと古い記事だけど、「Selecting Rows Randomly from a Large Table」をざっくり意訳しました。

多くの行数がある巨大なテーブルから、ランダムにサンプリングしてデータを取得したいことがあります。

ランダムにサンプリングするために、テーブルからTOP Nで選択することがあります。しかし、このサンプルではランダムではなく、必ずしも再現性はないですがテーブルの最初のN行を取得します。

小さなテーブルからランダムに行数を取得する場合には、一般的には次のようなクエリを使用します。

SELECT TOP 10 PERCENT *
FROM test
ORDER BY NEWID()

ポイントは、「NEWID()」関数を使用していることです。
NEWID関数は、グローバルに一意な識別子GUIDをメモリ上の各行に生成します。
GUIDでORDER BYによるソートをすると、ランダムにテーブルの行が並べ替えられます。
テーブルからランダムにサンプリングして最初の10%の行数を取得できます。

ランダムにデータを取得したい場合、よくNEWIDクエリの仕様が提案されます。
小さなテーブルであれば、とてもシンプルに動作します。
でも、NEWIDクエリは大きなテーブルで使用すると、大きな問題を引き起こします。
tempdbデータベースにテーブルのすべての行をコピーして、ORDER BYを実行します。
この場合、2つの問題が起こります。

  • 通常、ソート処理は大きなコストがかかります。ディスクI/Oが多く必要で、長い時間かかります。
  • もっとも最悪なケースでは、tempdbが大量の容量を必要とします。

tempdbを使用せずに、あまり遅くなく、ランダムに行を取得するには、次のような方法があります。

SELECT * FROM test
WHERE (ABS(CAST(
(BINARY_CHECKSUM(*) *
RAND()) as int)) % 100) < 10

基本的な考え方は、テーブルの各行にランダムで0から99の間の数字を生成して、指定の%数字よりも小さい値をランダムですべての行から選択するというものです。
この例では、10%をランダムで取得したいので、10よりも小さい値をもつ行を選択しています。

BINARY_CHECKSUM関数は、指定したカラムの値をベースにチェックサム値を生成します。
異なる行どうしでは、チェックサム値は異なる値になります。

チェックサムは行の値が変わらない限り毎回同じ値を返してしまうため、完全なランダム値を入手することができません。この問題を解決するために、RAND関数を追加します。

RAND関数は、ごちゃまぜな値を返します。これで、クエリを発行するたびに行に毎回ことなる値をランダムに取得できます。ABSとCAST関数を使用することで、BINARY_CHECKSUM(*)*RANDが返すマイナス値をfloatに変換します。

BINARY_CHECKSUM(*)は、*だとコストが高いので特定列を指定することをお勧めします。

SELECT * FROM test
WHERE (ABS(CAST(
(BINARY_CHECKSUM
(keycol1, NEWID())) as int))
% 100) < 10

BINARY_CHECKSUMクエリは、ソートが不要で、時間とI/Oは線形になります。

実験

1億行、7億行、14億行のテーブルに対して、NEWIDとBINARY_CHECKSUMをテストしました。

1億行

NEWID:14秒

BINARY_CHECKSUM:0.7秒

7億行

NEWID:134秒

BINARY_CHECKSUM:10秒

13億行

NEWID:253秒

BINARY_CHECKSUM:21秒

Vagrant 1.6 プレビュー機能:Windows ゲストOS

$
0
0

Vagrant Blog:Feature Preview: Windows Guests

Vagrant 1.6 では、Vagrantに重要な機能が追加されます。
Linux環境と同様に簡単にWindows環境を管理することがVagrantで可能になり、Varantとして公式にサポートします。

勘違いしないでください、Windows上でVagrantを使用することはサポートしています。
Vagrantは一年間Windows上での動作をサポートしてきました。
Vagrant 1.6 では、Vagrant 環境内での(VirtualBox、Hyper-V、EC2上での)Windows動作をサポートします。

Vagrant 1.6 でWindowsゲストのサポートを提供し、Linux環境同様に、Windows環境をサインアップし、ソフトウェアのインストールや設定にPowerShellスクリプト、Chef、Pupetなどを使うことができます。

Linux環境では、Vagrant ssh、Windowsゲストには、Windows環境にリモートデスクトップにコマンド一つでアクセスできるVagrant rdpが提供されます。

VagrantはWindowsへの通信に、SSHまたはWinRMを使用します。
WinRMは、とても便利です。

WinRMのサポートは、新しい1.6からです

Vagrant.configure("2") do |config|
	# ...
	config.vm.communicator = "winrm"
end

Vagrant 1.6 プレビュー機能:グローバルステータスとコントロール

$
0
0

Vagrant Blog:Feature Preview: Global Status and Control

新しいコマンド「global-status」が追加されます。

Vagrantコマンドは、Vagrantfileと同じディレクトリか、サブディレクトリでしか操作できませんでした。
Vagrant 1.6 では、Vagrantfileが存在しなくても、どのディレクトリからでもVagrant環境をグローバルにコントロールできます。

$ vagrant global-status
id       name    provider           state              directory
---------------------------------------------------------------------
4174bb6  web     virtualbox         stopped            c:/hashicorp/foo
72a2e4d  default vmware_workstation running            c:/hashicorp/bar
865a979  default virtualbox         suspended          c:/hashicorp/baz

「global-status」コマンドを実行すると、Vagrant環境で作成された環境が表示されます。

グロバールステータスは、マシン情報としてマシンのIDと名前、場所、状態を返します。

マシンIDを使用すると、どこからでもVagrantコマンド(destroy、up、suspend)を実行することができます。

$ vagrant ssh 72a2e4d
Welcome to Ubuntu 12.04.3 LTS (GNU/Linux 3.8.0-29-generic x86_64)
vagrant@vagrant:~$

LocalDBが開発(プログラムの設計、開発、およびテスト)専用と思う理由

$
0
0

MSDNフォーラムで「LocalDB をどう考えますか?どう捉えていますか?」っというスレッドでLocalDBの話題で盛り上がっていました。

LocalDBはアプリケーションと共に配置し、本番のアプリケーションでも使用できる、つまり開発専用ではないという事実があります。

マイクロソフトの人がBlogでどういう風に語っていたか、セミナーでどういう風に語っていたかは、一旦わきに置いて、Microsoftが会社としてどう定義しているかを確認してみましょう。

ここで言う会社としての定義は、「マイクロソフト ソフトウェア ライセンス条項 MICROSOFT SQL SERVER 2014 EXPRESS LOCALDB」を参照するのが良いかと思います。
(C:\Program Files\Microsoft SQL Server\120\License Terms)

一部分だけを抜粋。

1. インストールおよび使用に関する権利。お客様は、お客様のプログラムの設計、開発、およびテストを行うために、任意の数の本ソフトウェアの複製をお客様のデバイスにインストールして使用することができます。

うーん、本番アプリケーションで使用できるようには読み取れないです。

お客様は、以下を行うことはできません。
• 本ソフトウェアを商用ソフトウェア ホスティング サービスで使用すること。

少なくとも、有償のオンラインサービスで使用してはいけないと明示されていますね。
では、組み込みは…となると、やっぱり第一条の文面からすると、
ダメで、「プログラムの設計、開発、およびテスト」に限定されているように思います

ただ、自分は法律の専門家ではないので、ライセンス条項をどう解釈するか、どう捉えるべきかは言えないので、私見ってことで…。

ちなみに、再頒布については以下のように書かれていました(まぁ、これも抜粋)。

• お客様は、本ソフトウェアのオブジェクト コード形式 (以下「再頒布可能なコード」といいます) を複製して再頒布することができます。および、
• お客様は、お客様のプログラムの頒布者に対して、お客様のプログラムの一部として再頒布可能コードの複製および頒布を許可することができます。

再頒布できるとは言え、LocalDBの使用権利が「お客様のプログラムの設計、開発、およびテストを行うために」というのは変わらないので、通常運用としては使用できないと思います。

SQL Serverで、SELECT結果でUPDATEする方法

$
0
0

SELECT結果を挿入したい場合は、次のような文法で書けます。

INSERT INTO <テーブル名> (<列名>,<列名>,<列名>)
SELECT
    <列名>,<列名>,<列名>
FROM
    <テーブル名> WHERE <条件>

わかりにくいので、具体的なコードを書くと次のような感じ。

INSERT INTO table (col1,col2)
SELECT col1,col2
FROM
    test
WHERE
    col1= 'test'

挿入じゃなくて、SELECT結果を用いて、更新したい場合は次のようにします。

UPDATE <テーブル名>
SET
    <テーブル名>.<列名> = <テーブル名>.<別のテーブル名>.<列名>
FROM
    <テーブル名>
INNNER JOIN
    <別のテーブル名>
ON
    <テーブル名>.id = <別のテーブル名>.id

わかりにくいので、具体的なコードを書くと次のような感じ。

UPDATE Table
SET
    Table.col1 = other_table.col1,
    Table.col2 = other_table.col2
FROM
    Table
INNER JOIN
    other_table
ON
    Table.id = other_table.id

MSDNでは、「他のテーブルのデータに基づいてデータを更新する」で説明されています。


Windows Explorerで、ドットで始まるファイルを作成する方法

$
0
0

ファイル名がドットで始まって拡張子が無いファイルをWindowsで作成しようとすると、

image

 

たとえば、「.gitignore」のようなファイル名にすると、

 

image

 

「ファイル名を入力してください」と言うエラーが発生します。

 

image

 

そんな場合は、.gitignoreをタイプした後に続けて、ファイル名の最後にドットをつけると作成できます。

 

.gitignore.

 

正しく作成できます。

 

image

Windows Live Writer 2012 のダウンロード

$
0
0

WindowsでBlogを書くときには、Windows Live Writerを使うのが一番楽でいいと思う。
画像投稿とかも楽。

いつもPCをリストアした後に、Windows Live Writer をインストールするんだけど、ダウンロード場所を見つけるのに、意外と苦労するのでメモしておこう。

最新版(と言っても、バージョン2012だけど)のダウンロードは、次の場所からダウンロードできる。

検索サイトで探しても、うまくヒットしないのが本当もったいない。
あとは、バージョンアップして、もっと使いやすくなってほしいところだけど、まぁ2012バージョンでも十分便利なので、まだ使ったことが無い人はぜひ。

SQL Server 2014 インメモリOLTP性能のホワイトペーパー by Dell

$
0
0

DELLが、Dell PowerEdge R920で、SQL Server 2014インメモリOLTPによる性能を、NVMe PCIe Flashカードと関連されて評価した資料を公開しています。

Accelerate SQLServer 2014 IN-MEMORY OLTP performance with Dell PowerEdge R920 and NVMe PCIe Flash cards

image

 

通常のドライブ > PCIe SSD > インメモリOLTP > インメモリOLTPとPCIe SSD
の順番に早くなっています。
インメモリでも十分早いのですが、SSDとインメモリの組み合わせになった時に爆速になっているのが興味深いです。

その反面、CPUに負荷はきています。

image

Git Diff Margin Visual Studio Extension

$
0
0

Git Diff Margin

Visual Studio Galleryダウンロード
リリースノート
ソースコード

Visual Studioのエクステンションで、Visual Studioの編集ウィンドウ(レフトマージン、スクロールバー)をフックしたい場合は、このエクステンションのソースコードが参考になります。

機能

image

  • Visual Studio 2010からVisual Studio 14までをサポートしています。
  • 全ての変更があったファイルのクイック表示
    変更行の青表示
    新しい行の緑表示
    削除した行の赤表示
    Visual Studioフォントと色オプションでの全てのカラー設定ができる
  • 変更のUndo
  • 古いコードのクリップボードへのコピー
  • ズームへの対応

xunit.net を使った個人的メモ

$
0
0

インストールしておくと便利なもの

  • Xunit
  • xunit.extensions
  • FluentAssertions
  • xunit.runner.visualstudio
    Install-Package xunit.runner.visualstudio –Pre

テスト対象の指定方法

image

こんな感じに、ソリューションの中でプロジェクトを分けた時に、どうやってテスト対象を指定するのかなと悩んだぐらい初心者。

次のように、プロジェクト参照を設定してあげればOKなんですね。

image

テストエクスプローラーにxunitのテストが表示されない

image

こんなの感じのテストコードを書いたのだけど、テスト一覧に表示されない。
原因は、public classじゃないから。
publicにしてあげたら、テスト一覧に表示された。

image

テストウィンドウにも表示される。

image

意味

[InlineData(hoge,hoge)]

テストメソッドに引数を渡せる。
それで複数のテストシナリオを定義できる。

[Theory]

シナリオテスト。

上の定義と合わせて一つなのかな?次のように並べて書いた。

image

InlineDataが一つでも通らなかったら、テストとして失敗と判定される。

SQL Server でBulk Load の性能改善方法

$
0
0

Options to Improve SQL Server Bulk Load Performanceで、Bulk Loadをする際に、どのような手段をとると一番性能が良くなるのかの調査結果が後悔されています。

シナリオは次の4つ

  1. BULK Load
  2. tablockをして、BULK Load
  3. インデックスを削除して、tablockをして、BULK Loadしてからインデックス再作成
  4. インデックスを削除して、tablockをして、BULK Loadしてからインデックス再作成してから、復旧モデルの変更
Test ScenarioCPU (ms)ReadsWritesDuration (ms)
1522917513834157704142978
230763151651385757296844
3207631955893962967510
4530061959163965162766

結論としては、4番目の「インデックスを削除して、tablockをして、BULK Loadしてからインデックス再作成してから、復旧モデルの変更 」が最速になります。

ALTER DATABASE testdb SET RECOVERY SIMPLE;
DROP INDEX testtable.idx_testtable_col2;
DROP INDEX testtable.idx_testtable_col3;
BULK INSERT testdb.dbo.testtable
FROM 'C:\testtable.dat'
WITH (FORMATFILE = 'C:\testtable_formatfile.fmt', TABLOCK);
CREATE INDEX idx_testtable_col2 on testtable (col2 asc);
CREATE INDEX idx_testtable_col3 on testtable (col3 asc);
ALTER DATABASE testdb SET RECOVERY FULL;

SQLで重複行を削除する方法 : SQL Server

$
0
0

巨大なテーブルから重複行を削除するにはどうしたらいいのでしょうか。
stackoverflowの「How can I remove duplicate rows?」で解答がついていますので紹介します。

前提となるテーブルは次の定義となっています。
ポイントは、完全に重複しているわけではない点。理由は、identity定義を使って主キーは自動インクリメントされているから。

MyTable
-----------
RowID int not null identity(1,1) primary key,
Col1 varchar(20) not null,
Col2 varchar(2048) not null,
Col3 tinyint not null

方法1

DELETE MyTable
FROM MyTable
LEFT OUTER JOIN (
   SELECT MIN(RowId) as RowId, Col1, Col2, Col3
   FROM MyTable
   GROUP BY Col1, Col2, Col3
) as KeepRows ON
   MyTable.RowId = KeepRows.RowId
WHERE
   KeepRows.RowId IS NULL

intではなく、GUIDを使っている場合は、MIN(RowID)の代わりに次のクエリを使います。

CONVERT(uniqueidentifier, MIN(CONVERT(char(36), MyGuidColumn))) 

方法2

;WITH cte
     AS (SELECT ROW_NUMBER() OVER (PARTITION BY Col1, Col2, Col3
                                       ORDER BY ( SELECT 0)) RN
         FROM   #MyTable)
DELETE FROM cte
WHERE  RN > 1

ちなみに、方法2のほうが実行プラン上では低コストになりやすいようです。

回答者が、ベストアンサーになってる方法よりも自分の回答のほうがすばらしい!アピールで記載しています。

image


LINQ で SQL の LIKE の「%」を使う方法

$
0
0

SQLであいまい検索のクエリをLINQで書くにはどうすればいいのでしょうかっという質問が、stackoverflowで投稿されていました。

たとえば、次のような絞込みクエリを書き換えるとします。

where a.testRow like '%/12/%'

LINQでは、次のように書く。

.Where(a => a.testRow.Contains("/12/"))

他には、「.StartsWith()」とか「.EndsWith()」とかも使えます。

Google の Admin Reports API を .NET Client で使用する際の Scope 指定方法

$
0
0

Google APIs Client Library for .NET : OAuth 2.0」で、Books APIを使用した例が掲載されている。他のAPIを使用する際にも、やり方は変わらないのだけど、Scope指定方法に多少悩んだのでメモしておく。

Admin Reports APIの場合は、次のように書く。

UserCredential credential;
            using (var stream = new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    new[] { ReportsService.Scope.AdminReportsUsageReadonly },
                    "user", CancellationToken.None, new FileDataStore("usage"));
            }

Admin Reports APIのScopeは2種類ある。どのように指定するかは、Google.Apis.Admin.reports_v1.xmlを参照すると分かりやすい。

  • ReportsService.Scope.AdminReportsAuditReadonly
  • ReportsService.Scope.AdminReportsUsageReadonly

Google の OAuth 2.0 を .NET Client で使用する際の jsonファイルの設定方法

$
0
0

「Google APIs Client Library for .NET : OAuth 2.0」で、認証方法が説明されている。その中で、APPIキーやSecretキーをjsonファイルの読み取りで対応する方法が説明されている。
その際に、jsonファイルのプロパティを設定してあげないと存在しないと言われてしまうので注意。
# サンプルのファイル名と、ダウンロードできるファイル名が微妙に違うので注意(複数形とかね

UserCredential credential;
            using (var stream = new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
            {
                credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GoogleClientSecrets.Load(stream).Secrets,
                    new[] { ReportsService.Scope.AdminReportsUsageReadonly },
                    "user", CancellationToken.None, new FileDataStore("usage"));
            }

「client_secret.json」ファイルのプロパティで、出力ディレクトリにコピーを「常にコピーする」に設定。

image

google API を呼ぶために、X509Certificate2を使用して、サービスアカウント認証をする際に、証明書ファイルが見つからないとエラーになる場合の対処方法

$
0
0

Google APIs Client Library for .NETの解説ページで、Service accountのサンプルプログラムが掲載されている。しかし、このコード、環境によってはエラーが発生してしまう。

指定されたパスが見つかりません。
   場所 System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr)
   場所 System.Security.Cryptography.X509Certificates.X509Utils._QueryCertFileType(String fileName)
   場所 System.Security.Cryptography.X509Certificates.X509Certificate.LoadCertificateFromFile(String fileName, Object password, X509KeyStorageFlags keyStorageFlags)
   場所 System.Security.Cryptography.X509Certificates.X509Certificate..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)
   場所 System.Security.Cryptography.X509Certificates.X509Certificate2..ctor(String fileName, String password, X509KeyStorageFlags keyStorageFlags)
   場所 Loki.googleAdminReportMVC.usageReportService.<Run>d__e.MoveNext() 場所 e:\Loki\Loki.googleAdminReportMVC\usageReportService.cs:行 22

英語だと「The certificate file does not exist.」、日本語だと「指定されたパスが見つかりません。」と言われてしまう。

問題のコードは次のようなコード。

            var certificate = new X509Certificate2(@"~/key.p12", "notasecret", X509KeyStorageFlags.Exportable);
            ServiceAccountCredential credential = new ServiceAccountCredential(
               new ServiceAccountCredential.Initializer(serviceAccountEmail)
               {
                   Scopes = new[] { ReportsService.Scope.AdminReportsUsageReadonly },
               }.FromCertificate(certificate));

間違いなくファイルもあるのだけど、無いと言われる。

仕方が無いので次のように、「HostingEnvironment.MapPath」を使うように書き換えたら、エラーが出なくなった。

ちなみに、上記コードだと、まだ認証が通らないので、プロパティを一つ追加している。

            var certificate = new X509Certificate2(HostingEnvironment.MapPath(@"~/key.p12"), "notasecret", X509KeyStorageFlags.Exportable);
            ServiceAccountCredential credential = new ServiceAccountCredential(
               new ServiceAccountCredential.Initializer(serviceAccountEmail)
               {
                   Scopes = new[] { ReportsService.Scope.AdminReportsUsageReadonly },
                   User = "hoge@example.com"
               }.FromCertificate(certificate));

Google APIs Client Library for .NET で OAuth 2.0 認証(サービスアカウント)すると、Google.Apis.Requests.RequestError エラーが出る場合の対応方法

$
0
0

Google APIs Client Library for .NETの解説ページで、Service accountのサンプルプログラムが掲載されている。しかし、このコード、エラーが出てしまう。

エラー内容は次のとおり。

Google.Apis.Requests.RequestError
Caller does not have access to the customers reporting data. [403]
Errors [
    Message[Caller does not have access to the customers reporting data.] Location[ – ] Reason[forbidden] Domain[global]
]

これは、サービス認証をどのユーザーアカウントで実施するかを指定していないから。
なので、特権管理者アカウントなど、APIアクセスできるアカウントをUserプロパティで指定してあげるといい。

            var certificate = new X509Certificate2(HostingEnvironment.MapPath(@"~/key.p12"), "notasecret", X509KeyStorageFlags.Exportable);
            ServiceAccountCredential credential = new ServiceAccountCredential(
               new ServiceAccountCredential.Initializer(serviceAccountEmail)
               {
                   Scopes = new[] { ReportsService.Scope.AdminReportsUsageReadonly },
                   User = "hoge@example.com"
               }.FromCertificate(certificate));
Viewing all 183 articles
Browse latest View live