Windows8.1用にxkeymacsをビルド

追記 2015/8/14
たぶん、画面のサイズを125%とか150%にするとまたボタンが隠れてしまいます。根本的な解決にはならないのでご注意ください。


Surface3にxkeymacsをセットアップして立ち上げたけど、プロパティダイアログで、ボタンが隠れる問題に直面(^^;

xkeymacs-8.1

ダイアログリソースをいじればいいや、と思いxkeymacs-snap-110830のソースをダウンロードしてVisual C++ 2010 Express Edition + WDKでビルドしたんですが、以下のエラーでストップ。

Utils.cpp(461): error C2039: 'GetString' : 'CString' のメンバーではありません。

ふむふむ、GetStringがないんだったら、強引にキャストしてまえ!ってことで、

//修正前
memcpy(pMem, text.GetString(), nLength);

//修正後
memcpy(pMem, (LPCSTR)text, nLength);

で切り抜け。

xkeymacs.rcだけVisual Studio Communityで適当にサイズ修正。
プロパティーシートで使用されるフォントがメイリオになってしまうのが原因?
ソース追えるほどMFCに精通していないため、ダイアログリソースだけ場当たり的に修正してビルド。

今度はちゃんとボタンが表示されました。

xkeymacs-8.1-2

めでたし!

ファイルの置き場に置いてます (xkeymacs-only-win8.1) 無保証

最後にリリースされてから4年と久しくバージョンアップされていないようですが、
Windows10も出ることですし、ダイアログ関連のメンテナンスリリースしてほしい<m(__)m>

中継サーバーを経由して社内LAN上のテストサーバーへ接続する

いや、まぁ、タイトルどおりです(^^ゞ 実験です。興味本位です。(^^;;;

社内のテストサーバーに自宅から、好きなときに、どうにかしてSSH接続できないものか・・・?とてもじゃないけど、「VPN設置して家からアクセスさせてください」とか、「ルータのポート一個開けて、俺っちのテストサーバーへルーティングして」とか、そんな都合のいいことが通る(許可される)はずもありません(^^;;;

幸いなことに、テストサーバーはCentOS6で、社内の資産管理システムからは除外されている。というか、社内のIT管理部門にLinuxを扱えるシステム精通者はいません(笑) プロバイダー業も一時期やってたから数年前にはそれなりに詳しい人がいたかもしれませんが、経営方針とやらが変わってからそういう人たちは殆どいなくなった。会社から技術が無くなるって、ほんとあっけないですね。

ってなわけで・・・・?

サーバー・ネットワークの素人なりに考えた結果、やはりポート転送を使うしか方法がないかなと。ただ、家にあるPCはブロードバンドルーター(もはや死語か?)の内側のLANに繋がっているので、単純にSSHポート転送すればいい話ではないのは、自明です。

素人なりに考えたあげく、下記のように、現在契約しているVPSサーバーを中継してSSHポート転送を行えば、やりたいことは可能なはず・・・

ポートフォワーディングでファイヤーウォールを越える2

まず、社内のテストサーバーから中継サーバーに逆ポート転送をかけます。下記のような感じでしょうか。

>> ssh -N -R 10022:localhost:22  user@xxx.xxx.xxx.xxx

これで、中継サーバーの10022番へアクセスしたら社内の22番ポート(SSHD)にアクセスできるようになった。ただ、これだと、社内のテストサーバーにログインするためには、いちいち中継サーバーにログインして、そこから、またsshでログインして・・・という風になるので、もう一つ、家のPCから中継サーバへポート転送してしまおう、というのが今回の実験の目的。

中継サーバーへポート転送するには、こんな感じ?

>> ssh -N -L 22:localhost:10022 user@xxx.xxx.xxx.xxx

理屈はあってると思うんだけど、これで家のPCのローカルポート22番へsshで接続すると、中継サーバーの10022番ポートへ接続され、さらに中継サーバーの10022番ポートは、社内のテストサーバーの22番ポートへ転送される。

別にこんなことしなくても、多段SSHすりゃいいじゃん、ってな声も聞こえますけど、SSHじゃなくて、たとえば社内のテストサーバーにFTP接続したい、ってな時だと、やっぱり中継サーバーへのポート転送を行わないとセキュリティ的にねぇ・・・。
(※実際には中継サーバーへの接続には鍵認証を使い、家のPC(Windows7)からはPortForwarderを使用して接続しています。)

どこかに穴を開ける(ポートを開ける)リスクを最小限に抑えつつ、その場しのぎの方法としてSSHポート転送はついつい銀の弾丸に思えてきます(^^;;;

ちなみに、一度試みようと、家に帰ってきて繋げてみたところ、接続できませんでした。テストサーバーでKeepAliveの設定をし忘れてしまって・・・接続が切れてしまってたとさ。トホホ。

追記:
後日 ~/.ssh/config ファイルにServerAliveInterval を設定して、完了。快適です。SSHポートだけじゃなく、FTP/HTTPポートも転送することでやりかけの仕事を家でできるようになった(^.^)

なんかの加減で社内テストサーバーから中継サーバーへの接続が切れてしまうと一切接続できなくなるのは困りもの。autosshを使えばいい、というブログ記事が多いけど・・・鍵認証にパスフレーズを入力するようにしてあるので、ちょっと無理かな。現状、切れたら終了~。

MySQL + UPDATE + PDOStatement::rowCount の罠

MySQLのセットアップはテーブル作成とかも含めて、非常に面倒なので、作成途中(開発中)はSQLiteで作って動作確認して、作成大詰めの段階でMySQLに切り替え完成・・・という工程はわりかし一般的?だと思う。ファイル一個でバックアップ・リストアも簡単で開発効率も上がります、僕は。

で、SQLite + PDO で何の問題もなくある程度コーディングが終わり、MySQLに移行して検証していると、おかしな挙動の解決に半日かかってしまった備忘録のエントリです。

データを空更新、特定の行を取得して、編集画面表示、その後、内容を変えずに同じデータで更新すると、update文は成功するのに、作用した行数が0を返す・・・。だいたい下のような感じ。

&lt;?php
/*************************************************************

  あらかじめ下記mysqlクライアントで実行

  &gt;&gt; CREATE TABLE test_table(id INTEGER,data CHAR(255));
  &gt;&gt; INSERT INTO test_table values(1,'Kenji Nakagawa');

**************************************************************/
$pdo = new PDO('sqlite:log.sqlite');

if(modify_name(1,'Kenji Nakagawa'))
{
  header('location: list.php');
}

function modify_name($id,$name)
{
  global $pdo;

  $rv = false;
  $sql = 'update test_table set name = ? where id = ?';

  if(false !== ($stmt = $pdo-&gt;prepare($sql)))
    {
      if(false !== ($result = $stmt-&gt;execute(array($name,$id))))
        {
          $rv = $stmt-&gt;rowCount();
        }
    }

  return $rv;
}

この一連のコーディングでの最大の失敗は、rowCount()メソッドが返す行数で、update文の成功・失敗を判断したところ。分かってしまえば、何でもないことだけど、はまってしまった。

分かったことは、

MySQL + UPDATE文の実行では、PDOStatement::rowCount() は「実際に変更した(あった?)行数」(←ここ重要)を返す

・・・・ということ。

元々のレコードと同じデータをupdateすると、update文の実行はfalseは返さない(成功する)が、rowCount()は1ではなく、0を返す・・・。PHPサイトのドキュメントを検索したらちゃんと書いてありました・・・・とほほ(T-T)

UPDATE を使用する場合、MySQL では新旧の値が同じときには更新処理を行いません。 このことから、必ずしも mysql_affected_rows() の返す値が マッチする行の数と一致するとは限りません。返す値は実際に更新処理が行われた 行の数です。

そんな・・・・僕が勉強したときにちょろっと読んだMySQL入門書には書いてない!(笑)

ってわけで、解説書なんかで勉強するときは、いかに良い本に巡り会うことの重要性を改めて痛感しました。。。

tar コマンド

会社で使用しているテストサーバー機(CentOS 5.5)は、ちょっと前に流行ったネットトップの小さいPC。小さくて場所を取らず、簡単に持ち帰りもでき、重宝していたのですが・・・CPUがATOM Dプロセッサなので、いかんせんパフォーマンスが悪いです。

4月後半ぐらいから社内機の一斉Windows7化の波にさらされ(^^ゞ、メインマシンが置き換えられた結果、今までメインとして使っていたWindowsXPが余ったので、これを新しいテストサーバー機にしようと画策。速攻でCentOS6に入れ替えた。

データベースやソース管理のリポジトリなど、結構めんどくさいデータが山ほどあるので、ぜんぶ TARでまとめてホットコピーすることにした。

UNIX系のコマンドには精通していないので、TARを打つにもいちいちネットで検索(笑)

パーミッションやユーザー・グループ情報を保持したままTARで固めて、新マシンで解凍しようと思ったんだけど・・・ネットで検索して引っかかってくるブログ記事の情報が錯綜してて・・・

(1) 固めるときにも、解凍するときにも、-p オプションが必要
(2) 解凍するときだけ、-p オプションを付ければ良い。
(3) -p オプションを付けて固めて、解凍するときに、–same-owner が必要

など、いろんな情報が出てきて、正直、どれが正しいのかわからんかった。

man tar を読むと・・・、

-p , –same-permissions, –preserve-permissions
許可情報を全て抽出する

とある。
抽出ってことは、固めるときは、デフォルトでユーザー情報やパーミッションは保持されてるってこと???
抽出って、extract ですよね・・・? 違うのかな???

よく分からん。

結局、固めるときは、 tar cvzf xxxx.tar.gz target 、解凍するときに、tar xvzfp xxxx.tar.gzでやった。rootユーザーで。

ちゃんとコピーされったっぽい(^^ゞ 明日から、テストサーバーの検証作業をちょびちょびやっていこう・・・いけるのかな?、また、ルーチンワークが入る前に、終わらせたい。

コマンドバーにボタンを追加

Windows7のコマンドバーネタ(備忘録)です(^^ゞ

会社のPCがやっとXPからWindows7になりました。ええ、やっとです。XPのサポートが完全に終了したので、たぶん、仕方なくです(笑) どうせなら、Windows8.1にして欲しいものです。

さて、Windows8以降はエクスプローラシェルにもリボンUIが採用され、Vista/7のフォルダウィンドウの上部にくっついていたコマンドバーが消えてしまいました。Windows8以降のフォルダウィンドウはなかなか使い勝手よく、色んな設定をわざわざコントロールパネルを辿らずとも変更できるのですが・・・Windows7ではその辺使い勝手が悪いです。まぁ、見た目は圧倒的にWindows7の方が好きなのですが・・・。

あ、そうそう、フォルダウィンドウ内で、CTRLキーを押しながらマウスホイールを回すとアイコンサイズが変わるって知ってました? おいら、今日初めて知った・・・。ちょー便利。

と、そんなことは、どーでもよく。。。

隠し属性のファイルの表示・非表示を簡単に切り替えるようにしたくて、コマンドバーにスクリプトを登録しました。
toggle

コマンドバーへのボタン追加は、3年ぐらい前にコマンドバーの記事を書いていたので、隠し属性のファイルの表示・非表示を行うスクリプトを書いて、レジストリに登録するだけ。

/*
  隠しファイルの表示・非表示トグル スクリプト
  ちょいと変更 at 2014/4/28
*/
(function()
{
  var wShell = WScript.CreateObject("WScript.Shell")

  try
    {
      var Key="HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced\\Hidden";
      var Value = parseInt(wShell.RegRead(Key));

      // レジストリ・キー(Key)の値(Value)が、1の時は非表示、2の時は表示なので入れ替え。
      // ・・・逆だったっけ?ま、いいや。
      wShell.RegWrite(Key,(Value & 1) + 1,"REG_DWORD");

      //現在開いているフォルダウィンドウのコレクションを得る。
      var sWindows = WScript.CreateObject("Shell.Application").Windows();

      /*
      現在開いているフォルダの数だけ、ループを回して更新する。
      Itemメソッドで得られるオブジェクトはInternetExplorerオブジェクトなので、
      Refresh()メソッドで表示を更新させる(F5キーを押すのと同じ)。
      */ 
      var i = sWindows.Count - 1;
      while(i >= 0)
        sWindows.Item(i--).Refresh();
    }
  catch(e)
    {
      WScript.Echo(e);
    }
})(); 

レジストリへの登録は「エクスプローラー(Windows7)のコマンドバーにボタンを追加する」をご参考に。