pslaboが試したことの記録

はてなダイヤリーからはてなブログに引っ越してきました

この日記は現在実行中の減量記録を含む個人的なメモとして始めましたが、最近はコンピュータやガジェット、ハック、セキュリティネタのほうがメインになっております。

はてなダイヤリー時代はカテゴリ分けが適当だったのですが、これはそのうち直します。


検証用のWindows Server仮想マシンの自動ログイン設定をregコマンドで作る

Windows Serverで環境を作っては試し、また初期状態から再度つくる、みたいなテストを繰り返していたらログインが面倒になってきました。しかしレジストリ設定を手作業でレジストリエディタで書くのもそれはそれでめんどくさいし、.reg ファイルを作って読み込ませるのも微妙にめんどくさい。

そこで reg コマンドのコピペだけですませることにしました。

以下のコマンドのパスワード部分だけを書き換えてコピペすれば設定が完了します。

reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoAdminLogon  /t REG_SZ /d "1"
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultUserName /t REG_SZ /d "Administrator"
reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v DefaultPassword /t REG_SZ /d "パスワード"

Windows向けのsudo的なコマンドをDelphiで書く

先日、こういう記事をポストしたのですが、ここで調べた内容に基づいて Delphi で sudo 的なコードを書いてみました。

pslabo.hatenablog.com

やりたいことは、別のコマンドを管理者権限で実行したいだけなので、Delphi コマンドラインアプリケーションのプロジェクトを選択し、ShellExecute を 'run as' で実行するだけの簡単な実装です。

実行するコマンドとパラメータを以下のように取得して ShellExecute に渡しています。

  • ParamStr(1) で実行すべきコマンド名が渡される
  • ParamStr(2) - ParamStr(ParamCount) にコマンドへの引数が入る

実際の実装はこちら。

program sudo;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows,
  ShellAPI,
  System.SysUtils;

var
  LParamIndex: Integer;
  LCommand   : String;
  LParameters: String;
  LCurrentDir: String;
  LhInstance : HWND;
begin

  if ParamCount >= 1 then
    try
      LCommand := ParamStr(1);

      if ParamCount >= 2 then
        for LParamIndex := 2 to ParamCount do
          LParameters := LParameters + ParamStr(LParamIndex) + ' '
      else
        LParameters := '';

      LCurrentDir := ExtractFilePath(ParamStr(0));

      LhInstance := ShellExecute(
        0,
        'runas',
        PChar(LCommand),
        PChar(LParameters),
        PChar(LCurrentDir),
        SW_SHOW);
    except
      on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
    end;

end.

Windows 向けにChocolateyでインストールできるsudoの内部実装がVBScriptだったので、代替案を探す

セキュリティポリシー等の問題でVBScriptが禁止になったのだけど、Chocolateyでインストールできるsudoは内部実装でVBScriptが使われていたので、代替案を探すことにします。

とりあえず、検索して見つかったものをいくつか列挙してみました。

qiita.com

orebibou.com

tkntkn.hatenablog.jp

できればコマンドプロンプトPowerShellの両方で使いたいだけど、良い代替方法がいまいち見当たらない感じ。

場合によっては、自分で実装してしまうというのも一つの解決策かもしれません。あるいは BitBucket や GitHub で公開されているコードをビルドするとか。

qiita.com

自分が欲しい機能は管理者権限が必要なプロセスを起動させたい、というだけです。UNIX の sudo のように一般ユーザ権限のコマンドからパイプで sudo 経由で実行したコマンドに何かを渡したいという要望はありません。

そうすると、手元にある Delphi で Win32/Win64 コマンドラインアプリケーションとして作成し、ShellExecute するアプリを作ればよいような気がしてきました。

複数の画像を順番どおりにPowerPointのファイルに差し込む作業を自動化する

とある事情でキャプチャ画像を順番通りにPowerPointのスライドに差し込む必要が出たのですが、こんなのを手作業でやるのはめんどくさいのでで自動化する方法を探したところ、RubyPowerPoint ファイルを生成できるものを見つけました。

github.com

そこで、これを使って画像を pptx に差し込む処理を汎用的に使えるようなスクリプトにしてみました。現時点ではとりあえず動くレベルの試験実装ですが、最低限の目的は達せられました。awk が動く環境なら、Linux (Windows Subsystem for Linux), macOS, cygwin のどれでも動くはずです。

作業に必要な powerpoint gem のインストール

gem install powerpoint でOKです。(必要に応じて su とか sudo してください)

画像一覧を標準入力から受け取って powerpoint gem で画像を差し込むスクリプトを生成する処理をつくる

とりあえずこんなふうに awk で実装してみました。ファイル名は generateImagePptx.awk とでもつけておきます。

#!/usr/bin/awk -f
BEGIN {
        print "#!/usr/bin/ruby"
        print ""
        print "require \"powerpoint\""
        print "@deck = Powerpoint::Presentation.new"
        print ""
}

{
        printf "title      = \"%s\"\n", $1 ;
        printf "image_path = \"%s\"\n", $1 ;
        print  "@deck.add_pictorial_slide title, image_path" ;
        print ""
}

END {
        print  "@deck.save('images.pptx')"
}

これで images.pptx に対して、指定されたファイル一覧を差し込む(正確には新規作成する)処理が生成できます。

実行してみる

png形式のファイルをまるごと渡すとスクリプトが作られるので、たとえば次のように実行するとよいでしょう。

 ls *.png | generateImagePptx.awk | ruby

こうすれば、生成されたスクリプトがそのまま ruby 経由で実行されます。

差し込まれる画像の順番が思ったとおりにならない場合の対処

ファイル名の命名規則によっては思った通りの順番にならないことがあります。たとえばファイル名が slide-1.png, slide-2.png のように命名されていると、ls の結果が次のようになってしまい、意図通りの順になりません。

$ ls -l *.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-1.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-10.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-2.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-3.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-4.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-5.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-6.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-7.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-8.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-9.png

画像ファイルのタイムスタンプが時系列に並んでいるならば、-tr をつけてあげれば次のように意図通りに並びます。

$ ls -ltr *.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-1.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-2.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-3.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-4.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-5.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-6.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-7.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-8.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-9.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-10.png

しかしなんらかの理由でタイムスタンプが時系列順ではない場合は、この方法では思った通りの順番で出力できません。

$ ls -ltr *.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-1.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-3.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-4.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-6.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-7.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-8.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-9.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:49 slide-10.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:50 slide-5.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:50 slide-2.png

この場合は sort コマンドを間に挟みつつ slide-number.png-t - で slide と number.png に分割し、number.png の部分を -k 2 -n で数値順ソートすれば意図通りの順番に並べることができます。

$ ls *.png | sort -t - -k 2 -n | xargs -n 1 ls -l
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-1.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:50 slide-2.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-3.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-4.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:50 slide-5.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-6.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-7.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-8.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:48 slide-9.png
-rw-r--r--  1 pslabo  staff  0  6 15 06:49 slide-10.png

したがって、次のように実行すればファイルのタイムスタンプによらず順番に画像を差し込んだ pptx を生成できます。

 ls *.png | sort -t - -k 2 -n | generateImagePptx.awk | ruby

これでとりあえず最低限の目的は達せられていますが、ruby を別コマンドで実行しなければならない点がイマイチです。ここは print や printf の後に | "/usr/bin/ruby" をつけて awkスクリプト内で ruby と連携したほうがよいですね。

試験用データが作成できるサービスを探してみる

できれば日本語の試験用ダミーデータを作りたいので、見つけたサービスをとりあえず列挙していきます。

人名、会社名、住所などのダミーデータを最大3000件まで作れる。出力はCSVまたはSQLroopidea.com

個人情報を最大5000件作れる。HTML, XML, CSV, タブ区切りで生成可能。 kazina.com

テスト用のクレジットカード番号 www.find-job.net

Windows10の仮想マシンを新規インストール後にやっておきたい設定

作業用の仮想マシンを壊してしまい、環境を作りなおそうと思ったけど、ゼロからの環境構築は、たまにしかやらないので案外めんどくさいです。

そこで、このエントリに自分の作業用環境に必要なものを一旦書き出していき、まとまったら最終的にキッティング作業用に自動化するためのスクリプトPowershell またはバッチファイル)を作ろうと思います。

コンピュータ名を設定する

コマンドプロンプトから実行する方法。

wmic computersystem where name="%computername%" call rename name="New-PC-Name"

PowerShell から実行する方法。

Rename-Computer -NewName "New-PC-Name" -Force -Restart

仮想マシンが自動でスリープしないようにする

初期設定だと勝手にスリープして困るので、スリープしないようにします。

powercfg.exe /change standby-timeout-ac 0
powercfg.exe /change monitor-timeout-ac 0

www.atmarkit.co.jp

Windows Update を実行する

(New-Object -ComObject Microsoft.Update.AutoUpdate).DetectNow()

news.mynavi.jp

Windows Subsystem for Linux をインストールする

bash が使えないのはつらいのでこれは普通に入れる。

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

あとは適当なディストリビューションWindows Store から選んでインストールする。

(Windows10 LTSC や Windows Server だとサイドローディングになるので、それぞれ別の対応が必要なことに注意が必要)

docs.microsoft.com

Chocolatey をインストールする

いろいろインストールするのを自動化したいので、そのために Chocolatey を入れます。

@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

chocolatey.org

参照するDNSサーバを Google Public DNS に変更する

様々な理由によりDNSサーバによる名前解決をインターネット側から見た場合の挙動に揃えたいので、DNSサーバを Google Public DNS に変更します。

netsh interface ip set dns "Ethernet0" static 8.8.8.8 primary
netsh interface ip add dns "Ethernet0"        8.8.4.4

よく使うフォントをインストールする

コーディング用のフォントとかを入れます。

よく使うショートカットをつくる

Snipping Tool とか、ペイントとか、意外に使うことが多いので、ここらへんはタスクバーに予め作っておく

よく使うツールを入れる

必須でインストールするのはここらへん。

Firebase Cloud Messaging で node からメッセージを飛ばす

DelphiAndroid 向けにリモートプッシュ通知を送信しようと思ったら GCM はオワコンで FCM が必要なのに、Delphi は FCM に正式対応していない中、とりあえずサーバでの送信側実装とクライアントでの受信側実装のプロトタイプを作っている。

クライアント側は一応動くようになったので、サーバ側の試作のために一旦 node で書いてみることにします。

ここらへんを読みながら...

https://firebase.google.com/docs/admin/setup?hl=ja https://firebase.google.com/docs/cloud-messaging/admin/send-messages?hl=ja

なんとなくノリだけで書いたコードがこちら。

var admin = require('firebase-admin');

admin.initializeApp({
  credential: admin.credential.cert({
  "type": "service_account",
  "project_id": "fcmremotepush-xxxxxxx",
      .
      .
      .
  databaseURL: 'https://fcmremotepush-xxxxxxx.firebaseio.com'
});

// This registration token comes from the client FCM SDKs.
var registrationToken = 'メッセージ送信対象デバイスのトークン';

// See documentation on defining a message payload.
var message = {
    "notification":{
      "title":"Portugal vs. Denmark",
      "body":"great match!",
    },
  token: registrationToken
};

// Send a message to the device corresponding to the provided
// registration token.
admin.messaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });