2016年12月23日金曜日

【PowerShell】スクリーンショット2

■フリーソフトが使用できない職場なので、 WinShotも使用できない。仕方なく、 PowerShellでスクリーンキャプチャする。 
少し改良したので再掲
##########################################################################################
# 注意事項
#  ・ドライブ直下のフォルダ(例えばc:\tmpなど)は権限が無いため、
#    本スクリプトでは作成できないことがあります。事前に作成して下さい。
#  ・実行ポリシーが変更されていない場合、(Set-ExecutionPolicy RemoteSigned等)が必要です。
##########################################################################################
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# 出力先ファイルパス
$filePath = "c:\tmp\evi\C{0:000}.png"
#$filePath = "c:\tmp\evi\" + $(Get-Date).ToString("yyyyMMdd") + "\C{0:000}.png"

# Jpeg,Gif,Bmp,Pngから選択する。
$fileKind = [System.Drawing.Imaging.ImageFormat]::Png

# スクリーンキャプチャして、Graphicsオブジェクトを生成
$rect = [System.windows.forms.Screen]::PrimaryScreen.Bounds
$bitmap = New-Object System.Drawing.Bitmap($rect.Width, $rect.Height)

$graphics = [System.Drawing.Graphics]::FromImage($bitmap)
$zero = New-Object System.Drawing.Point(0, 0)
$graphics.CopyFromScreen($zero, $zero, $bitmap.Size)

# フォルダ作成、フォルダがすでに存在するエラーは非表示。他のエラーも黙らせるので注意。
$dirPath = Split-Path $filePath -parent
New-Item -path $dirPath -type directory -ErrorAction SilentlyContinue

# ファイル名を決定。順に、以下の処理を行う。
# 1000までの数字を生成、ファイル名をフォーマットに従い決定、ファイルが存在するかチェック、最初の1件を取得、変数に格納を行う。
1..1000 | % { $filePath -f $_ }  | Where { (Test-Path $_) -eq $false } | select -First 1 | sv resultFile

# ファイル保存
$bitmap.Save($resultFile, $fileKind)

##########################################################################################
# ファイル作成後処理。フォルダやファイルを開く。必要に応じて、コメントアウトする。
##########################################################################################
$shell = New-Object -ComObject Shell.Application # explorer ieの一覧を取得

#============================================================================
# 拡張子に対する既定のアプリケーションで開く。
#============================================================================
#ii $resultFile

#============================================================================
# ペイントで開く。
#============================================================================
#mspaint $resultFile

#============================================================================
# IEで開く。(毎回新しいウィンドウで開く。)
#============================================================================
#$ieCom = New-Object -ComObject InternetExplorer.Application  # IEで開く。
#$ieCom.Navigate($resultFile)
#$ieCom.Visible = $true

#============================================================================
# IEで開く。初回のみIEを1つ開き、2回目以降はウィンドウを更新する。
#============================================================================
# 対象のウィンドウのみ取得。
$ie = $null
$locationURL = "file:///" + $dirPath.Replace("\", "/")
$shell.windows() | where {($_.LocationURL -like $locationURL + "*") -and ($_.Name -eq "Internet Explorer")} | select -First 1 | sv ie

# オープン済みのIEが取得できなかった場合は、IEを開く。
if ($ie -eq $null)
{
    $ie = New-Object -ComObject InternetExplorer.Application
    $ie.Width = 700
    $ie.Height = 300
    $ie.Left = 1000
    $ie.top = 300
    $ie.AddressBar = $false
}

# IEで作成したファイルを開く。
$ie.Navigate($resultFile)
$ie.Visible = $true

#============================================================================
# エクスプローラを開く。
#============================================================================
$exp = $null
$locationURL = "file:///" + $dirPath.Replace("\", "/")
$shell.windows() | where {($_.LocationURL -like $locationURL) -and ($_.Name -eq "エクスプローラー")} | select -First 1 | sv exp
if ($exp -eq $null)
{
    Start "explorer " -Args $dirPath -Wait
    $shell.windows() | where {($_.LocationURL -like $locationURL) -and ($_.Name -eq "エクスプローラー")} | select -First 1 | sv exp

    $exp.Width = 700
    $exp.Height = 300
    $exp.Left = 1000
    $exp.top = 0
    $exp.AddressBar = $false
    $exp.Document.SortColumns = "prop:System.DateModified;"
    $exp.Document.CurrentViewMode = 5
    $exp.Document.IconSize = 150
}

$exp.Refresh2()

2016年12月22日木曜日

【ESXi】【NUC】ESXi6.5 USB3(PCIPassThrough)

◆過去3度に渡って誤った情報(NUC+ESXi6.0、ESXi6.5でUSB3.0コントローラを PCI Pass Throughできないという誤った情報) を書いてしまったが、NUC(D54250WYK)にESXiをインストールしてUSB3.0をPCI PassThrough(VM DirectPass I/O)できるか再調査した。

 ⇒ 再調査の結果、実現可能と分かった。


VMDirectPassI/O要件
に記載のある通り、passthrough.map に記載するだけだった。記載内容は、後述。詳細は分かってないのだが・・・。
タイトルはESXi6.5について書いているが、ESXi6.0も可能かもしれない。

◆USB3.0コントローラのPCI Pass Through手順
1. BIOSでxHCI ModeをEnable(下記のSmart Auto⇒Enableにする)にして保存し、PC起動。

2. vSphere Host Clientにログインし、SSHの有効化。

3. tera termでESXiのIPを指定。

4. ユーザ名を指定し、チャレンジレスポンス認証を選択し、OKボタン押下。

5. パスワード入力。

6. /etc/vmware/passthru.mapを編集。

7. 「8086 9c31 d3d0 default」 を記載(ハードウェアによって値は変わる。適宜読み替えること。8086 9c31はintel NUC D54250WYKのxHCI(USB3.0コントローラ)。lspciコマンド、lspci -nコマンドで調べられる。)。

8. ESXiを再起動し、vShpere Host Clientにログイン。
9. [管理]-[ハードウェア]を選択し、下記のようにxHCIを有効にし、再起動。

10. 起動完了したら、再度vShpere Host Clientにログインし、該当PCの設定の編集画面を開き、[その他のデバイスの追加]を選択。

11. PCIデバイスを選択。

12. 画面下部のPCIデバイス1のコンボボックスでxHCIを選択。(保存後再度、下記画面を開き直して、xHCIになっていることを確認する。何故か反映されないことがある。)

◆仮想マシンを起動すると、USB-HDD、TVキャプチャが表示された。


◆肝心の速度
 ①USB3.0 ディスク1(xHCI有効にした後のベンチマーク結果)

 ②USB3.0 ディスク2(xHCI有効にした後のベンチマーク結果)

 ③USB2.0の時の速度は以下。(過去に上記①と同じディスクをUSB2.0で使用していた時のベンチマーク結果)


安定性は、これから検証する。
一時期ESXi、KVM、Xenを行ったり来たりしてたが、USB3.0の安定が確認できたら、今後はESXiで行くと思う。

ESXi4の頃から挑戦してたが、5年越し位でやっとできた・・・(当時は、NUCではなく、ZBoxとかだった。)。つーか3年くらい前からNUC(DC53427HYE)にしたが、ESXi5の頃にはできてたんじゃ・・・。

  • PCのスペック等
    • プラットフォーム:NUC D54250WYK
    • BIOS:WYLPT10H.86A.0042.2016.0704.1441
    • CPU: Core™ i5-4250U Processor
    • メモリ:16GB
    • 内部ストレージ:SSD(ウルトラ II mSATA SSD SDMSATA-512G-G25C)
    • 外部ストレージ:MARSHAL MAL355EU3R(USB-HDD5台(USB3.0))
    • TVチューナ:PX-W3U3(USB2.0 TVチューナ)※
    • ESXiバージョン:6.5.0 (Build 4564106)
※ 録画のみ使用し、視聴はしない(一応リモートデスクトップで視聴可能だが、見れたもんじゃない)。

2016/12/28 追記: 1週間程度使ったがUSB-HDD・USB-TVチューナ特に問題無し。

2016年12月18日日曜日

【ESXi】【NUC】ESXi6.5 USB3(PCIPassThrough)について訂正

◆NUCをESXi6.0から6.5にアップグレード
 しかし、VMDirectPass I/O(PCI Pass Through)は相変わらずグレーアウトされている。以下の0000:00:14.0がUSB3.0。仕方なく、USB2.0(USB EHCI #1)を使用。もはやNUC+ESXiでUSB3.0はあきらめるしかないのか?
 xenの時は、警告でresetがどうこう出てた気がする(それでもUSB3.0は使えていた)ので、FLRに対応してないせいかな?それともNUCのPCIeが3.0に対応してないせいかな?

VMDirecetPass I/O使用のハードウェア要件

下記に記載したが、USB3.0パススルー可能だった。
【ESXi】【NUC】ESXi6.5 USB3(PCIPassThrough)
そのため、以下の記事は誤り。




◆USB Pass Throughは、まだ試してない。
 ESXi6.0やそれ未満でも有効にはできていたが、しばらく使い続けると不安定になる現象があった。これが治ってくれてばいいんだが、データが壊れたりするので、運用して試すのが億劫。

◆USBデバイスが認識しなくなった。
 ESXi6.5にアップグレードした後、PCI PassThroughしているUSBController配下のHDDが認識しなくなった。ESXi6.5の後と書いたが、実は他にもいくつか設定変更したのでESXi6.5が原因かは不明。
 BIOSの設定で、以下のxHCIモードをDisableに変更したら、USB HDDが認識した。ESXi6.0の時は、Autoにしてたはずなんだが、う~ん、なんだろう?



【ESXi】【NUC】ESXi6.0から6.5にアップグレード

◆アップグレード手順
1. vmware (英語)のサイトでregister。
2. アンケートに回答。
3. VMware-VMvisor-Installer-6.5.0-4564106.x86_64.isoをダウンロード。
4. USBメモリをfat32でフォーマット。使用したUSBメモリは以下の4GB。

5. unetbootin(フリーソフト) を起動し、上記でダウンロードしたisoイメージをUSBメモリに書き込み。

6. 途中上書き確認があるが、すべて上書きを選択。
7. USBメモリをESXiアップグレード対象PCに挿して、PC起動。
8. インストーラが起動したら、Enterキー押下。

9. F11キー押下。

10. ESXi6.0のインストールされているディスク(アップグレード先)を選択。今回はSanDisk~が該当のディスク。ちなみにImationはインストール元のUSBメモリ、JMicronはゲストOSでUSBコントローラPCI をPassThroughして、USBポートに挿しているUSB-HDD。

11. 今回はアップグレードなので、一番上がXになっていることを確認し、Enterキーを押下。

12. F11キーを押下。

13. しばらく待つ。

14. 完了。

15. ブラウザで、以下にアクセス。

16. ログイン後、6.5.0になっていることを確認。当然、アップグレード前のVMは残っている。


◆環境
 ホストPCの構成
  • PlatForm:NUC(D54250WYK)
  • CPU:Intel Core i5-4250U
  • メモリ:16GB
  • ドライブ:SSD(SanDisk SDMSATA-512G-G25C)

2016年12月1日木曜日

【SQL Server】ストアドプロシージャでGETDATE()複数回実行

◆コード①:ストアドプロシージャ内で複数回実行
CREATE PROC [dbo].[PROC1]
AS
BEGIN
  SELECT GETDATE();
  WAITFOR DELAY '00:00:01';
  SELECT GETDATE();
END
GO

EXEC [dbo].[PROC1]

◆結果①
 


◆コード②:1つのSELECT内で複数回実行(重い処理を挟む)
-- データ作成
CREATE TABLE tb_tmp (col1 INT, col2 INT);

DECLARE @i INT = 0, @loop_count INT= 100000;

WHILE @i <= @loop_count
BEGIN
  INSERT tb_tmp VALUES(@i/10,@i)
  SET @i += 1
END
GO

CREATE PROC [dbo].[PROC1]
AS
BEGIN

SELECT GETDATE();
-- GETDATA()を複数と重い処理を含むSELECTを実行
SELECT date1, date2, GETDATE() AS date3
  FROM (
    SELECT date1, GETDATE() AS date2
      FROM (SELECT GETDATE() AS date1) AS a
      CROSS JOIN (
        tb_tmp AS b FULL OUTER JOIN
        tb_tmp AS c ON b.col1 = c.col1 -- 重い結合
      )
  ) AS d
  CROSS JOIN
  tb_tmp  -- 重い結合
  GROUP BY date1, date2
;
SELECT GETDATE();
END
GO

EXEC [dbo].[PROC1]

◆結果②
 

◆コード③:1つのinsert内で複数回実行(1000行insert)
CREATE TABLE dbo.tb_tmp (col1 INT, col2 DATETIME);
GO

CREATE PROC [dbo].[PROC1]
AS
BEGIN
  INSERT dbo.tb_tmp (col1, col2) VALUES
     (0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())
    ,(0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())
    ,(0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())
    ,(0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())
    ,(0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())


<中略>

    ,(0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())
    ,(0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())
    ,(0,GETDATE()),(1,GETDATE()),(2,GETDATE()),(3,GETDATE()),(4,GETDATE()),(5,GETDATE()),(6,GETDATE()),(7,GETDATE()),(8,GETDATE()),(9,GETDATE())
  ;

  select distinct(col2) from dbo.tb_tmp;

◆結果③
 

2016年11月16日水曜日

【ESXi】【Windows】ディスク容量拡張

ESXi6.0上のゲストOS(Windows10)の容量がなくなったのでディスクを拡張してみた。



1. ゲストOSをシャットダウンしておく。

2. VSphere Host clientで該当の仮想マシンの[設定の編集]メニューを開く。

3.以下のようにハードディスク1の30GBから40GBに変更し、「保存」ボタン押下。


4. OSを起動し、Winロゴキー+X(Windows10の場合)を押下し、ディスクの管理を選択。


29.56GBの領域に9.43GBの領域をつなげたいのだが、上記のように隣接していない場合は簡単に結合できない。以下のツールを使用する。

EaseUS Partition Master(以下epmとする)

5. epmをダウンロードして、インストール。

6. epmを起動し、下から2番目のパーティションを選択し、右クリック。

7. 「パーティションのサイズ調整/移動」を選択。

8. 「パーティションのサイズ調整/移動」画面上部の青いバーをドラッグして右に移動


9. 同様に真ん中のパーティションも移動する。

10.上記手順で29.56GBと9.43GBが隣接する。

11. 29.56GBのパーティションを選択し、右クリック。

12. 「パーティションのサイズ調整/移動」を選択。

13. 画面上部の青いバーの右端のつまみをドラッグして、容量を拡張する。
以下のように38.98GBのパーティションになる。


14. メインメニューの [一般]-[変更を適用]を選択する。
⇒再起動がかかり、しばらくするとパーティションが変更された状態で再起動される。


  • なぜか一部ゴミ領域ができてしまった。
  • それとたぶん手順ミスのせいで、回復パーティションがE:、F:になった?

備考
VMWareToolsが入ってなかったせいか、最初は9.43GBの領域が認識されなかった。VMWareToolsインストール後、認識された。


2016年11月12日土曜日

【C#】ループ内で複数処理と複数ループの速度差

■共通の事前処理(20億個のデータを用意しておく)
◆ソースコード
var list = Enumerable.Repeat(1, 1000 * 1000 * 200).ToList(); // 大量データ生成

① ForEach、ラムダを2回で、ループ内処理を1回
◆ソースコード
int sum1 = 0, sum2 = 0;
list.ForEach((it) => sum1 += it);
list.ForEach((it) => sum2 += it);
◆結果
 1回目:Time=01.97秒, sum1=200000000, sum2=200000000
 2回目:Time=02.09秒, sum1=200000000, sum2=200000000

② ForEach、ラムダを1回で、ループ内処理を2回
◆ソースコード
int sum1 = 0, sum2 = 0;
list.ForEach((it) => { sum1 += it; sum2 += it; } );
◆結果
  1回目:Time=01.08秒, sum1=200000000, sum2=200000000
  2回目:Time=01.03秒, sum1=200000000, sum2=200000000

③ forループを2回で、ループ内処理を1回
◆ソースコード
int sum1 = 0, sum2 = 0;
for (int i = 0; i < list.Count; i++) sum1 += list[i];
for (int i = 0; i < list.Count; i++) sum2 += list[i];
◆結果
  1回目:Time=01.61秒, sum1=200000000, sum2=200000000
  2回目:Time=01.45秒, sum1=200000000, sum2=200000000

④ forループを1回で、ループ内処理を2回
◆ソースコード
int sum1 = 0, sum2 = 0;
for (int i = 0; i < list.Count; i++) { sum1 += list[i]; sum2 += list[i]; }
◆結果
  1回目:Time=00.85秒, sum1=200000000, sum2=200000000
  2回目:Time=00.78秒, sum1=200000000, sum2=200000000

⑤ Aggregateを2回で、ループ内処理を1回(用途が適切でないと思うが、見てみる)
◆ソースコード
var sum1 = list.Aggregate((elem1, elem2) => elem1 + elem2);
var sum2 = list.Aggregate((elem1, elem2) => elem1 + elem2);
◆結果
  1回目:Time=08.39秒, sum1=200000000, sum2=200000000
  2回目:Time=05.65秒, sum1=200000000, sum2=200000000

■結論
当然と言えば、当然だが、処理時間は2倍になる。
コードの読みやすさは、人によって違うだろうけど、①かなぁ?

◎環境
 ●速度確認した仮想マシン
  • CPU:4
  • メモリ:2GB
  • OS:Windows10
  • 仮想マシン:VMWare ESXi6.0U2
  • Visual Studio 2015 Enterprise(試用版)
  • 構成:Releaseでビルド
  • デバッグ情報(ビルドの詳細設定):none
  • Visual Studio ホスティングプロセス:無効
 ●ホストPCの性能(参考)
  • CPU:Intel Core i5-4250U
  • メモリ:16GB
  • ドライブ:SSD