VBScriptをエンコードしたVBEをHTAに使用する

 数年前にHTA+VBScriptで簡単に作った画面ツールに、メールを送信する機能を追加する事になりましたが、送信に使用するSMTPが認証を必要とするので、パスワードは暗号化しなくてはなりません。

 VBScriptだと、暗号仕様やIV、キーがスクリプトなので読めてしまうという事。どうしたものかと、下記を発見。スクリプトをエンコードし、読めない形に出来る模様。知らなかった。。

[blogcard url=”https://qiita.com/yoshi389111/items/7e4cfcf95ad986c56dcf”]

 やろうと思えばデコードも出来てしまうようですが、基本的に要員専用の業務端末なので、まあそこまでは気にしないという事にしときます。

 下記のようにHTA側には難読化していないこれまでのVBSとエンコードしたVBEの2つのスクリプトを指定して使用します。

<script language=”VBScript” src=”easytool.vbs”>
</script>
<script language=”VBScript.Encode” src=”crypt.vbe”>
</script>

 

 IEサポート終了のアナウンスがあり、そろそろHTAも終了かと思いきや、まだ大丈夫そうです。。

ROBOCOPY再び

 Windows端末にインストールする形で提供しているアプリについて、変更都度インストールしなきゃいけないのが面倒という話があり、ファイルサーバからリソースをコピーする形にしようと思います。
 対象のアプリは下記のようなフォルダ構成で、基本的に初期インストール以外はファイルを配置するのみです。

アプリルートフォルダ¥src
アプリルートフォルダ¥img
アプリルートフォルダ¥data
アプリルートフォルダ¥log

 上記フォルダのうち、logとdataのフォルダはコピー対象外となります。
 また、アプリ変更時は数人に先行して使ってもらって評価した後に他の利用者へ配布するという運用なので、端末側に新しいリソースがある場合はコピーしないようにします。

結果こうなりました。

robocopy ファイルサーバの所定フォルダ アプリルートフォルダ /E /XO /XD log data /NDL /NFL /NJH /R:2 /W:3

前回使ったrobocopyコマンドを参考に、/XD でlogとdataのフォルダを対象外にし、/E /XO /XD で端末側が新しければコピーしないという形にします。

ADOでCSVファイルを読み込むと255文字以上でエラーになる

 ちょっと前にVBScriptで作られたツールがあるのですが、最近になってエラーが出るとの連絡。
エラーになるケースは、CSVファイルを読み込んで255Byteを超えている値を扱う時と判明。
対象のツールは実装上ADOが使われており、下記のようにCSVへアクセスしてます。

Set objADO = CreateObject("ADODB.Connection")
objADO.Open "Driver={Microsoft Text Driver (*.txt; *.csv)};DBQ=CSVファイルのフォルダ;ReadOnly=1}"
Set objRS = objADO.Execute("select * from CSVファイル名")

Do Until objRS.Eof = True
   '1番目の項目
   colum1 = objRS(0)
'具体的な処理は省略
   objRS.MoveNext
Loop

対象のCSVファイルが改行を含む値を扱う都合でADOを使ったようなのですが、どうやら、CSVテキストドライバとしての仕様上、255を超える項目数だったり、255を超えるサイズといった、昔ながらの壁がある模様。
回避策としては、Schema.iniで逃げるのが定番らしいのですが、試したところエラーにはならないが、255文字超が勝手に切られる形に・・・

というか、これ以上ADODBについて調べる時間が無駄!!なので、テキストファイル読み込みとして作り直しました。。

こちらを少し参考にして、さらにダブルクォーテーション内のカンマも考慮し(ここではカンマは削除してます)、ADOのレコードセットっぽく1レコード毎に配列へ列の値をセットしてから処理を行っていきます。

Const sCsvFileName = "C:\Users\XXX\data.csv"
Dim objFSO
Dim objFile
Dim strLine,SpltTmp
Dim i,iDimPos,colum1

Set objFSO = CreateObject("Scripting.FileSystemObject") 
Set objFile = objFSO.OpenTextFile(sCsvFileName)

Do While objFile.AtEndOfStream <> True
     'CSV列の最大数
     Redim strRec(12)
     strLine = ""
     Do While objFile.AtEndOfStream <> True
        strLine = strLine + objFile.ReadLine
        If (Len(strLine) - Len(Replace(strLine,"""",""))) Mod 2 = 0 Then Exit Do
        strLine = strLine + vbNewLine
     Loop
     iDimPos = 0
     For Each SpltTmp In Split(strLine,",")
        If iDimPos > 11 Then
           Exit For
        End If
        If Instr(SpltTmp,"""") = 0 Then
           strRec(iDimPos) = SpltTmp
           iDimPos = iDimPos + 1
        ElseIf Instr(SpltTmp,"""") = 1 And InStrRev(SpltTmp,"""") = Len(SpltTmp) Then
           If Instr(1, SpltTmp, """") = 2 Then
              strRec(iDimPos) = ""
           Else
              strRec(iDimPos) = Mid(SpltTmp,2,Len(SpltTmp)-2)
           End If
           iDimPos = iDimPos + 1
        Else 
           strRec(iDimPos) = strRec(iDimPos) + SpltTmp
           If InStrRev(SpltTmp,"""") = Len(SpltTmp) Then
              strRec(iDimPos) = Mid(strRec(iDimPos),2, Len(strRec(iDimPos))-2)
              iDimPos = iDimPos + 1
           End If
        End If
     Next

   '1番目の項目
   colum1 = strRec(0)
'具体的な処理は省略
Loop

objFile.Close

Windows10でHTAの画面フォントが崩れる

 少し前にHTAで作られたツールのWindows10対応をしていましたが、一部の画面で文字が巨大化したりで表示が崩れて目も当てられない状況。。

 でも全ての端末で起きる事象では無いらしく、特にパナのLet’s Note の場合に発生しているらしい。どうも、Win10のデスクトップ右クリックでディスプレイの設定を開き、「拡大縮小とレイアウト」が100%でないと崩れる模様。
 パナのLet’s Noteは、ディスプレイの解像度が高い為、文字を大きく表示したいと設定を変更する人が多いようです。

「拡大縮小とレイアウト」より設定を変更しながら対応結果の確認をしますが、HTAは「一部のアプリは、サインアウトするまで、拡大縮小の設定に応答しません」の対象なので、設定を変更してはサインアウトの繰り返しが必要。

 結局、HTAに書かれているCSSを確認したところ、%指定とかem指定とか結構適当になっていた事に起因している事が判明。
 フォントサイズを全てピクセル指定にして一件落着。

今どきはXCOPYでなくROBOCOPY

ファイルサーバからWindows端末にディレクトリ毎ファイルを同期させたいような話があり、昔ながらXCOPYのオプションなんだっけ?とググっていたところ、今はROBOCOPYなる便利なコマンドがある模様。

今回は、完全にディレクトリを同期させ、うざい出力も消したいので下記のコマンドで対応

robocopy \\fileserver\targetdir %USERPROFILE%\targetdir /mir /NDL /NFL /NJH

スタートアップにバッチを仕込んで、Windowsローカルアプリ更新時の同期とか簡単に出来ますね。

ZendFramework1でREST APIを試してみた

既存の業務アプリ内にある機能を外部から利用出来たらなあ・・・のような要件があり、RestAPIで実装を検討しました。対象のアプリは、今となっては・・・ですが、ZendFramework1が使われています。

こちらにいろいろ書いていますが、Zend_Rest_Controllerを使えばいいっぽい。

開発環境はEclipse + php + XAMPP
XAMPP内のphp/pearの中に、ダウンロードしたZendFramework1.12.20のZIPからlibrary内のZendを配置、XAMPP内のapache/conf/extra/httpd-xammp.confに該当プロジェクトのAliasをセットして環境ができました。

    Alias /testapp "C:/xampp/htdocs/TestAPP/html/"
    
        AllowOverride All
         Require all granted
    

テスト用のEclipceプロジェクトはこんな感じで最少構成。

.htaccess でindex.phpに仕向けます。

RewriteEngine on
RewriteBase /testapp/
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php

index.phpでdispatchします。

<?php
require_once 'Zend/Controller/Front.php';

$controller = Zend_Controller_Front::getInstance();
$controller->setControllerDirectory('../application/controllers');
$controller->setParam('noViewRenderer', true);

try {
	$controller->dispatch();
} catch (Exception $e) {
}

ControllerにZend_Rest_Controllerとして必要なメソッドを追加していきます。

<?php
require_once 'Zend/Rest/Controller.php';

class TestController extends Zend_Rest_Controller  {

    public function indexAction() {
		$this->getResponse()->appendBody("hello world " . $_REQUEST[param1]);
    }

    public function headAction(){
//TODO
    }
    public function getAction() {
//TODO
    }
    public function postAction() {
//TODO
    }
    public function putAction() {
//TODO
    }
    public function deleteAction() {
//TODO
    }
}

で、ブラウザから動作確認

URLをいろいろ意識すると難しそうですが、これなら簡単ですね。

Windows10でHTAがエラーになる

 HTA&VBSの構成で社内利用向けに作ったツール(社内端末はwin7)について、今後のWindows10導入へ向けて稼働確認をしたところ、エラーメッセージが出て動作しませんでした。

で、ネットでいろいろ調べたところ、
https://msdn.microsoft.com/ja-jp/library/cc817574.aspx
等を見ながら、

<meta http-equiv="x-ua-compatible" content="IE=9"/>

を入れてみたところ、エラーは無くなったのですが、画面レイアウトが崩れる結果に・・・
 社内ではこれからの新しい端末はWin10に、既存は当面Win7という方針なので、ツールとしてはどちらも同じように動作して欲しいところです。

 で、上記metaタグを外して結局何がエラーなの?と調べていくと、WMIのExecQueryを使った箇所がWin10ではエラーとなる事が判明。どうもセキュリティがらみの変更っぽいですが、詳細はよくわかりませんでした。。

 今回は別命令で置き換えが可能だったので、それに置き換えて問題無く動作するようになりましたが、画面だけは、フォントサイズの影響があったので微調整しておきました。
 そろそろHTAを止めたいのですが、Windowsマシン前提で簡易な画面ツールを作るとなると、まだ代替え手段が見つかりません。。

curlでパラメータを指定してWebページ上のファイルを取得してみる

 とあるWebサイトからファイルをダウンロードする作業を自動化したいという話があり、Linux上で動作するものという要件でしたので
とりあえずcurlでコマンドを作ってみました。対象サイトの認証はログイン画面からIDとパスワードを入力するという一般的な内容ですが、画面以外の対象サイトにおける認証の仕様については、何も情報が無くどうやらWebアプリ独自仕様のようです。
 ログイン画面でどんなやり取りがされているかと、FireFoxの開発ツールで確認し、POSTするパラメータを指定するコマンドを作成していきます。クッキーも指定してやってみますが、まだダメ。。

 今度はhttpヘッダの情報も開発ツールで確認しながら、必要そうなヘッダもcrulコマンドに指定すると、うまく動作しました。下記のような感じです。

ログイン画面

curl -X POST -L -b my.cookie -c my.cookie --header "Content-Type: application/x-www-form-urlencoded" -d "log=****&pwd=****" "https://targethost/login"

ダウンロードするファイルのGET

curl -L -b my.cookie -c my.cookie -o getout --header "Referer:https://targethost/aaaaa" https://targethost/files/targetfile.zip

 出来る出来ないはWebサイト側の作り次第かもしれませんが、とりあえずcurlでアクセスする事が出来そうです。
 とは言え、対象サイトの認証パスワードは定期更新が必要だし、他にもいろいろ対処が必要なので別の手段も考えた方がいいかもしれません。。。

UWSCを使ってみた。

前回の続きで、Windows系のサブネットを一括変更するツールを作ろうといろいろ調べてみました。
まずは、コマンドプロンプトなどで、
netsh interface ip show addres
を打ち、その出力から変更対象のネットワーク設定を取得し、それを元に、
netsh interface ip set address “ネットワーク名” static 192.168.1.101 255.255.254.0 192.168.1.1
といったネットワーク変更コマンドを発行するスクリプトを作ります。
 それをリモートから実行するのには、そのスクリプトをリモートマシンに配置して実行するという事なりますが、まずやってみたのがPsExec。net use でスクリプトをリモートマシンへコピーしてPsExecで実行するという内容ですが、2012Serverだとデフォルトではnet useもPsExecもFirewallで弾かれてしまいます。Firewallを無効にするとうまくいくのですが、Firewallとかセキュリティポリシーとか変えなきゃいけないならそれは本末転倒になってしまいます。
 結果、行きついたのが、UWSC。大抵のWindows系サーバはメンテナンスの都合でリモートデスクトップだけは有効になっているので、リモデ経由の作業を自動化するにはと発想を変えてUWSCを見つけました。下記を参考にさせて頂きました。

UWSCによるリモートデスクトップの一括自動操作スクリプト

微妙に2012ServerR2用のGUI操作に変更して使ってみました。
でも、結果的にはコマンドのみで完結しない作業だし、実行結果の証跡確保や確実性を求められる内容なので、やっぱり手作業が必要になってしまいました。ダイアログを出して手作業が終わったらボタンを押すみたいな。。
Windows系OS作業の自動化はインフラ側でそれに合わせた設定が事前にされてないと無理ですね。

TeraTermマクロでvi編集

 マシンが増えたのでサブネットを多数のサーバで一気に変えなきゃという話があり、対象サーバを確認したところ、Windows系もあるけどCentOSの6系が多いとの事。サブネットを変えるにはどうしたらいいのかいろいろ調べたと所、CentOS6だと一時的なのはifconfigで行けるけど、恒久的な変更だとコンフィグファイル更新が必要らしい。ちなみにCentOS7だとまた別のコマンドらしい。windows系は調査中。。。
 という事でリモート端末から一気に複数のサーバを更新するという要件なので、とりあえずはTeraTermマクロを作ってそれを各サーバに繰り返すという形にします。
 下記例はログインや引数処理、該当ネットワーク名の取得等は割愛し、viコマンドによるファイル編集をマクロで実行する箇所をサブルーチンにし、それをコールする内容です。コンフィグファイルは/etc/syscomfigにある該当ネットワークのファイル(下記のCONFFILE)に指定し、検索文字列(下記のSEARCHSTR)はPREFIX=、サブネットをBit24にするとして上書文字列(下記のAPPENDSTR)に24をセットしてサブルーチンをコールしています。

CONFFILE='/etc/sysconfig/network-scripts/ifcfg-eth0'
SEARCHSTR='PREFIX='
APPENDSTR='24'
call CHANGECONF
end

:CHANGECONF
;コンフィグ変更サブルーチン 
; CONFFILE	コンフィグファイル名
; SEARCHSTR	検索文字列
; APPENDSTR	上書文字列

timeout= 3
CMD = 'vi '
strconcat CMD CONFFILE
sendln CMD

;/を送る
send '/'
pause 1
; 検索文字へ移動
sendln SEARCHSTR
pause 1
strlen SEARCHSTR
sendkcode 333 result

; Rで上書き
send 'R'

send APPENDSTR

; エスケープ
send #$1B

send ':'
pause 1
sendln 'wq!'
pause 1
 
; 終了
return

コマンド打った後にwaitlnとかでは出来ないのでpauseを入れてとりあえずは動く形になりましたが、環境によりタイミングは変わるのでエラーハンドリングを追加した方が良さそうです。