2018年5月15日火曜日

Time Adapter for Excel のカスタムUI 実行時エラー

突如、Excel 2016 を起動するたびにこんなエラーメッセージが出るようになってしまいました。


どうしたものかと試した結果、こんな感じでうまくいきました。

「ファイル」-「オプション」-「アドイン」を開いて、一番下のコンボボックスで「COMアドイン」を選択して「設定」を押します。

Time Adapter for Excel なるアドインとやらのチェックをすべてオフにしてあげました。


これでうまくいきました。
そもそも何のためのアドインなのか、とかいうのは気にせずに切り捨ててしまいました(笑

2018年1月31日水曜日

Perl CGI でWEBサーバから高速に最新値を取得する

node.js あたりを使って非同期に動作させていればこんな苦労はないのでしょうがw

運用してるWEBサーバで、クライアント側の更新が必要かどうかだけを問い合わせたい時があります。

めったに変更されない値が変更されたかどうか、とか、

表示している内容が最新なのかどうか、とか。

jquery.timers.js を使って、everyTime, stopTime メソッドを呼び出せば定期的にサーバーに問い合せすることができます。

今回必要だったのが、データベース上のシーケンシャルなIDの更新状態です

ブラウザ上には一覧が表示されてるのですが、サーバー上では不定期にIDが追加されますので、現在表示している内容が最新かどうかを問い合わせたいわけです。

select count(*) from table where id>last_id; 

SQLを発行すれば、最新の件数がすぐに取得できます。

でもね、id ってときどきしか増えないのに、できるだけ早く検知するには everyTimeのインターバルを短くしなきゃならないわけで、無駄だなーと思うわけです。

しかも CGI 側では DBI::connect, disconnect, 戻り値のjsonだのXMLの出力を実施するんで、大量に利用者がいるとサーバーの負荷たるや、半端ない状態に陥ることまちがいなしです。

最新の値だけをファイルに書き込んでおいてそれを読みだすという方法も考えました。

それも open~close のオーバーヘッド考えるとわざわざ最新IDをファイルに保存するのは余計な処理と思ってしまいます。



そこで!


ファイルのタイムスタンプを利用してID管理できるんじゃなかろうか、という発想のもと作成したクラスが、これ。

package FastSerialHolder;
#============================================
# 2018/01/26 
#============================================
# 最新のIDを管理するクラス
# ファイルのタイムスタンプを使ってデータを保持させる
# ファイルの内容はアプリケーションごとに任意に書き込み
# atime<<32+mtime で63bitの値を管理する。
# ただし、atime はマウントにより使用していない場合もあるので注意
#============================================
our $FshBasePath = '任意のフォルダ';

#
#   コンストラクタ
#
sub new
{
    my ($self, $name, $group, $def_value) = @_;
    my $path = $FastSerialHolder::FshBasePath;
    #再帰的なディレクトリ作成はCGIでエラーになるので個別に作る
    #グループを階層化したい場合には、あらかじめディレクトリを作っておく
    if(! -d $path)
    {
        mkdir($path);
    }
    if(defined($group))
    {
        $path .= '/';
        $path .= $group;
        if(! -d $path)
        {
            mkdir($path);
        }
    }
    $def_value = 0 if(!defined($def_value));
    $def_value = 0 if($def_value !~ /^\d+$/);
    my $filename = $path . '/' . $name . '.fsh';
    my $object = bless {
  path => $path,
  name => $name,
  filename => $filename,
  current => $def_value,
  defualt => $def_value,
  handle => undef
 }, $self;
    if(! -e $filename)
    {
 $object->SetSerial($def_value);
    }
    return $object;
}

#
# 最新IDを取得する
#
sub GetSerial
{
    my ($self) = @_;
    if(! -e $self->{filename})
    {
        $self->{current} = $self->{default};
        return $self->{current};
    }
    my @st = stat($self->{filename}); # atime=$st[8], mtime=$st[9]
    my $hi = $st[8] << 32;
    my $lo = $st[9] & 0xFFFFFFFF;
    my $serial = ($hi + $lo) >> 1;
    return $serial;
}

sub SetSerial
{
    my ($self, $serial) = @_;
    if($serial < 0)
    {
        $serial = $self->{defualt};
    }
    if(! -e $self->{filename})
    {
        #ファイル作成
        if(open(my $fh, ">", $self->{filename}))
        {
            close($fh);
        }
    }
    my $rc = false;
    my $val = ($serial << 1);
    my $lo = ($val & 0xFFFFFFFF);
    my $hi = ($val >> 32);
    $rc = (0 < utime($hi, $lo, $self->{filename}));
    if($rc)
    {
        $self->{current} = $serial;
    }
    return $rc;
}
 

コメントなくてすみませんw

ようするに、ファイルシステムの更新時間とアクセス時間を変更して数値として取り扱うわけです。

実際には派生クラスを使って特定のグループごとにフォルダを分けて使うようにしてますが

使い方としては、最新値を取り出す場合は

my $idManager = new FastSerialHolder(名前,グループ名,初期値);
my $current = $idManager->GetSerial();
データベースが更新されたタイミングで

my $idManager = new FastSerialHolder(名前,グループ名,初期値);
$idManager->SetSerial(最新値);
とするだけです。



CGIでは、まず最新値があるかどうかの比較だけを行っておき、「あるよ」って返事が来たらデータベースにアクセスさせる別のCGIを呼び出すようにすればいいわけです。

実装して動かしてみると、とってもサクサクで快適です!

【備考というか補足というか】
実際に動かしたのは、CentOS 6.4 64bit です。

値を1ビットシフトしてるのは、ファイルシステムが秒の記録を2秒単位にしてた(昔の)記憶に頼ったもので、正しいかどうかは不明ですw

mkdir じゃなくて mkpath 使えと言われそうですが、初回生成時に STDOUTにprintするので、使わないようにしてます

stat で返される、atime と mtime が実際にファイルシステム上で何ビットなのか調べたけどわからなかったので(笑)、32bit だと思い込んで書いてます。

ファイルアクセスを高速化するために atime を無効にマウントされてる場合は 31bit しか扱えません。注意してください。(未検証)

0バイトでもクラスタ使っちゃうのかも・・・(そうなのかな?


画期的な方法だと思い込んでますが、きっと既出か、あるいはよくない実装って怒られるのか、どちらなのかもしれません。






2017年12月21日木曜日

先ほどのメールの添付ファイルのパスワードは***

メールの添付ファイルは、暗号化して添付すること。
暗号化パスワードは別メールで送付すること。

といったルールで運用されている企業が多いのはご存知のことと思います。
特に電器系のメーカーさんとかは全社でルール化されているようです。

主な理由は『メールが漏えいした場合に、重要なファイルの内容が漏えいすることを防ぐ』というものなのでしょう。
もし、メールが漏えいしているのであれば、別メールで送られたパスワード通知メールも当然漏えいしているわけですから、添付ファイルを暗号化してそのパスワードを別メールで送るなんてナンセンス極まりない。
送信時の手順もめんどくさいし、メールを受け取られた受信者側にもパスワードを入力してファイルを展開させる必要があるので、めんどくさいし失礼ではないか!
という御意見はもっともだと思います。
https://seasoft.co.jp/products/BizAttacher.html
たしかにご指摘の点についてはもっともではあります。
でも、この面倒な手順が事故を未然に防ぐことに一役買っていることも否定できません。

メールの送信事故というのは毎日のように発生しています。
・ファイルを添付するのを忘れて送信してしまった。
・複数の宛先あてのメールを Bcc ではなく To で送ってしまった。
・個人情報を含んだファイルを第三者に送ってしまった。
・見積書のファイルを別のライバル社に送ってしまった。
などなど。
メールを操作している方ならば、心当たりが少なからずあるはずです。

ファイルの暗号化は「メールが漏えいした場合の対策」だけではなく、メールの利用者がこういった人為的なミスを犯した場合にできるだけ事故の被害を少なくするのにとても有効です。

『自分はそんなミスはしないから大丈夫』

個人で運用しているメールであれば、そういった自信があれば問題ありません。
が、会社や団体などの組織の場合、『すべての人が何のミスもなくメールを運用している!』という保証はどこにもありません。

大手企業ならまだしも、多くの組織にはセキュリティの監視をするための部署や担当者さえいないのが現状で、誤送信の事故は頻繁に発生しています。

添付ファイルを暗号化しておいて、パスワードメールを別に送るようにルール化することは必ずしも無駄とは限らないのです。

Outlookをご利用の場合
https://seasoft.co.jp/products/BizAttacher.html

Becky!をご利用の場合
https://seasoft.co.jp/products/BkBizAttacher.html

これらのソフトで誤送信の事故を未然に防ぐのはいかがでしょう?
以上、CMでした。