Windows7 UACについて #VBS #WSH #Windows7
最近は、Windows XPからWindows7やWindows8に乗り換える機会があるかと思います。その際、XPで動いていたスクリプトやアプリケーションが動かない!なんてことが起こります。問題を引き起こしている原因は、Windows Vistaより導入されたUAC(User Access Control)という機能であることが多いです。
UACについては、このあたりを見ると理解ができるかと。
1. アプリケーション開発者向け Microsoft® Windows 7 対応アプリケーションの互換性
http://msdn.microsoft.com/ja-jp/library/windows/desktop/dd883236.aspx
2. Windows Vista,7 & 8のUAC対策について
http://www.trycut.com/uac.htm
UACが機能していると、具体的にどのような点に注意を配らなくてはいけないかといいますと。
A. ファイルやフォルダの保護機能で、システム領域(Windows、Program Filesなど)への実行、更新、書き込みが制限される
B. 管理者権限が与えられているユーザーでログインしても通常ユーザーと同じ権限しか書き込み や更新ができない
(※他にもあるようですが・・・省く!)
もちろんUACを無効にすることで回避はできます。が、UACのおかげでセキュリティ強化され、スパイウェアやマルウェアなどに知らぬ間にシステムを侵されにくくはなっているわけなので、無効にするのは得策ではないかと思います。UACが悪いんじゃないんです。むしろいてくれて感謝すべき機能なわけです。
じゃあ。回避策はあるのか?といいますと、上記のサイト2. に書かれているのですが、「管理者権限で起動」すればよいわけです。
で。ネットで落ちてるコードを参考にしつつ、枯れてる技術VBS(WSH)で書いてみた。サンプルコードは次の通り。
RunasExec.vbs
Option Explicit Function runasCheck() Dim objWMI, osInfo, os Dim i, args, strArgs, flgUac Dim curDir, objShell, execParam Const dQ = """" ' Double-Quote ' Check OS version Set objWMI = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2") Set osInfo = objWMI.ExecQuery("SELECT Version FROM Win32_OperatingSystem") For Each os in osInfo If Left(os.Version, 3) <= 6.0 Then Exit Function Next Set osInfo = Nothing Set objWMI = Nothing ' init Set args = WScript.Arguments strArgs = "" flgUac = False ' 引数から管理者権限で実行されているか確認 If args.Count > 0 Then If UCase( args.item(args.Length-1) ) = "/UAC" Then flgUac = True ' 実行しなおす前のディレクトリに移動 Wscript.CreateObject("WScript.shell").CurrentDirectory = args.item(args.Length-2) Else For i = 0 to args.Length - 1 strArgs = strArgs & " " & args.item(i) Next End If End If If flgUac = False Then ' カレントディレクリ取得 curDir = CreateObject("WScript.Shell").CurrentDirectory ' 引数に「curDir」と「/UAC」を追加し、管理者として実行しなおす execParam = dQ & WScript.ScriptFullName & dQ & strArgs & " " & dQ & curDir & dQ & " /UAC" Set objShell = CreateObject("Shell.Application") objShell.ShellExecute "wscript.exe", execParam, "", "RunAs", 1 Set objShell = Nothing Set args = Nothing Wscript.Quit End If End Function Call runasCheck() WScript.Quit Dim objWshShell Dim runScript runScript= "C:\setup.exe" Set objWshShell = WScript.CreateObject("WScript.Shell") objWshShell.Exec runScript
最後に
・毎回起動時にUAC確認ダイアログが出て面倒な人は、タスクスケジュールに登録しビルインAdministratorで起動(最上位の特権で実行)という荒業もあります。が、手動で個別設定が必要です。
・あと、ビルインAdministratorでログインするというのも手です。ただ、デフォルトだとログインできないので、以下のサイトを参考に設定してみると良いかと。
Win7jp Windows 7 総合情報サイト Win10への移行カウントダウン!
・久しぶりにVBSを書いてみたけど、VBSもまだまだ捨てたもんじゃないね!
Text::Mecab インストール #perl #cpan #形態素解析
形態解析のモジュールText::MeCabをCPANでインストールを試みたのですが、すんなりできなかったので、メモ...orz
もうテストが通らなくても強引にインストールしてしまおうと思ったのですが、どうにかできないかと調べていたところモジュール作者の牧大輔氏がgitの掲示板にperlのバージョンについて触れてました。
Install failure on make test · Issue #4 · lestrrat-p5/Text-MeCab · GitHub
で、早速バージョンを「v5.10.1⇒v5.16.2」にあげてみたところ、すんなりインストール完了。
・・・ Appending installation info to /usr/local/perl-5.16.2/lib/5.16.2/i686-linux/perllocal.pod DMAKI/Text-MeCab-0.20014.tar.gz /usr/bin/make install -- OK
所感
今回、インストールは「look Text::Mecabしてmake install」や「force intall」で無理やりでもできたと思います。真の原因は不明ですが、CPANモジュールは、すべてのプラットフォームで動作テストしているわけではないですし、推奨バージョン以外のperl環境で動作が保障されないのは至極当然のことだと思います。
そして、perlでXSを直接使っているモジュールのメンテナーは大変だなーと、ともに、牧さんの対応は紳士だなーと。
(参考)「cpan[1]>install Text::MeCab」のエラーログ
Writing MYMETA.yml and MYMETA.json cp lib/Text/MeCab/Dict.pm blib/lib/Text/MeCab/Dict.pm cp lib/Text/MeCab/Node.pod blib/lib/Text/MeCab/Node.pod cp lib/Text/MeCab.pm blib/lib/Text/MeCab.pm gcc -c "-I." "-I/usr/local/include" "-I." -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/local/include -DMECAB_MAJOR_VERSION=0 -DMECAB_MINOR_VERSION=994 -I src -Wall -Wextra -Wdeclaration-after-statement -Wc++-compat -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -DVERSION=\"0.20014\" -DXS_VERSION=\"0.20014\" -o xs/text-mecab-node.o -fPIC "-I/usr/lib/perl5/CORE" -DUSE_PPPORT -DTEXT_MECAB_ENCODING='"utf-8"' -DTEXT_MECAB_CONFIG='"/usr/local/bin/mecab-config"' xs/text-mecab-node.c gcc -c "-I." "-I/usr/local/include" "-I." -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/local/include -DMECAB_MAJOR_VERSION=0 -DMECAB_MINOR_VERSION=994 -I src -Wall -Wextra -Wdeclaration-after-statement -Wc++-compat -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -DVERSION=\"0.20014\" -DXS_VERSION=\"0.20014\" -o xs/text-mecab.o -fPIC "-I/usr/lib/perl5/CORE" -DUSE_PPPORT -DTEXT_MECAB_ENCODING='"utf-8"' -DTEXT_MECAB_CONFIG='"/usr/local/bin/mecab-config"' xs/text-mecab.c xs/text-mecab.c: In function ‘TextMeCab_create_from_av’: xs/text-mecab.c:70: 警告: ‘argv’ may be used uninitialized in this function /usr/bin/perl "-Iinc" /usr/share/perl5/ExtUtils/xsubpp -typemap /usr/share/perl5/ExtUtils/typemap xs/MeCab.xs > xs/MeCab.xsc && mv xs/MeCab.xsc xs/MeCab.c gcc -c "-I." "-I/usr/local/include" "-I." -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/local/include -DMECAB_MAJOR_VERSION=0 -DMECAB_MINOR_VERSION=994 -I src -Wall -Wextra -Wdeclaration-after-statement -Wc++-compat -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -DVERSION=\"0.20014\" -DXS_VERSION=\"0.20014\" -o xs/MeCab.o -fPIC "-I/usr/lib/perl5/CORE" -DUSE_PPPORT -DTEXT_MECAB_ENCODING='"utf-8"' -DTEXT_MECAB_CONFIG='"/usr/local/bin/mecab-config"' xs/MeCab.c xs/MeCab.xs: In function ‘XS_Text__MeCab_version’: xs/MeCab.xs:116: 警告: assignment discards qualifiers from pointer target type gcc -c "-I." "-I/usr/local/include" "-I." -D_REENTRANT -D_GNU_SOURCE -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/local/include -DMECAB_MAJOR_VERSION=0 -DMECAB_MINOR_VERSION=994 -I src -Wall -Wextra -Wdeclaration-after-statement -Wc++-compat -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -DVERSION=\"0.20014\" -DXS_VERSION=\"0.20014\" -o xs/text-mecab-clone.o -fPIC "-I/usr/lib/perl5/CORE" -DUSE_PPPORT -DTEXT_MECAB_ENCODING='"utf-8"' -DTEXT_MECAB_CONFIG='"/usr/local/bin/mecab-config"' xs/text-mecab-clone.c Running Mkbootstrap for Text::MeCab () chmod 644 MeCab.bs rm -f blib/arch/auto/Text/MeCab/MeCab.so LD_RUN_PATH="/usr/local/lib:/usr/lib" gcc -shared -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector --param=ssp-buffer-size=4 -m32 -march=i686 -mtune=atom -fasynchronous-unwind-tables -L/usr/local/lib xs/text-mecab-node.o xs/text-mecab.o xs/MeCab.o xs/text-mecab-clone.o -o blib/arch/auto/Text/MeCab/MeCab.so \ -L/usr/local/lib -lmecab -lstdc++ \ chmod 755 blib/arch/auto/Text/MeCab/MeCab.so cp MeCab.bs blib/arch/auto/Text/MeCab/MeCab.bs chmod 644 blib/arch/auto/Text/MeCab/MeCab.bs Manifying blib/man3/Text::MeCab::Dict.3pm Manifying blib/man3/Text::MeCab::Node.3pm Manifying blib/man3/Text::MeCab.3pm DMAKI/Text-MeCab-0.20014.tar.gz /usr/bin/make -- OK 'YAML' not installed, will not store persistent state Running make test PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'inc', 'blib/lib', 'blib/arch')" t/*.t t/*/*.t t/01-sanity.t ................ 1/? # 0.994 t/01-sanity.t ................ ok t/node/01_load.t ............. ok t/node/02_api.t .............. ok t/node/03_clone.t ............ ok t/node/04_clone_free.t ....... ok t/node/05_format.t ........... ok t/regression/01_tomi_args.t .. 1/2 # Failed test at t/regression/01_tomi_args.t line 41. # got: '記号,一般,*,*,*,*,* # 感動詞,*,*,*,*,*,* # 名詞,固有名詞,一般,*,*,*,* # 名詞,固有名詞,人名,一般,*,*,* # 名詞,固有名詞,組織,*,*,*,* # 名詞,固有名詞,地域,一般,*,*,* # 名詞,一般,*,*,*,*,* # 記号,一般,*,*,*,*,* # 名詞,固有名詞,一般,*,*,*,* # 名詞,固有名詞,人名,一般,*,*,* # 名詞,固有名詞,組織,*,*,*,* # 名詞,固有名詞,地域,一般,*,*,* # 名詞,一般,*,*,*,*,* # 記号,一般,*,*,*,*,* # BOS/EOS,*,*,*,*,*,*,*,* # ' # expected: 'BOS/EOS,*,*,*,*,*,*,*,* # 記号,一般,*,*,*,*,* # 感動詞,*,*,*,*,*,* # 名詞,固有名詞,一般,*,*,*,* # 名詞,固有名詞,人名,一般,*,*,* # 名詞,固有名詞,組織,*,*,*,* # 名詞,固有名詞,地域,一般,*,*,* # 名詞,一般,*,*,*,*,* # 記号,一般,*,*,*,*,* # 名詞,固有名詞,一般,*,*,*,* # 名詞,固有名詞,人名,一般,*,*,* # 名詞,固有名詞,組織,*,*,*,* # 名詞,固有名詞,地域,一般,*,*,* # 名詞,一般,*,*,*,*,* # 記号,一般,*,*,*,*,* # BOS/EOS,*,*,*,*,*,*,*,* # ' # Looks like you failed 1 test of 2. t/regression/01_tomi_args.t .. Dubious, test returned 1 (wstat 256, 0x100) Failed 1/2 subtests t/tagger/01_load.t ........... ok t/tagger/02_api.t ............ ok t/tagger/03_basic.t .......... ok Test Summary Report ------------------- t/regression/01_tomi_args.t (Wstat: 256 Tests: 2 Failed: 1) Failed test: 2 Non-zero exit status: 1 Files=10, Tests=2375, 1 wallclock secs ( 0.35 usr 0.03 sys + 0.78 cusr 0.07 csys = 1.23 CPU) Result: FAIL Failed 1/10 test programs. 1/2375 subtests failed. make: *** [test_dynamic] エラー 255 DMAKI/Text-MeCab-0.20014.tar.gz /usr/bin/make test -- NOT OK //hint// to see the cpan-testers results for installing this module, try: reports DMAKI/Text-MeCab-0.20014.tar.gz Running make install make test had returned bad status, won't install without force Failed during this command: DMAKI/Text-MeCab-0.20014.tar.gz : make_test NO
配列の重複要素をカウントし、まとめる #perl #shell
首題の通り、配列の重複要素をカウントして、まとめていくコードをperlで書きました。
SHELLで言うuniqコマンドのcオプション「#uniq -c」と同じ機能です。
ロジックは難しくないのですが、初期化エラーではまったのでメモ。
サンプルコードは以下の通り。
サンプルコード(disinct.pl)
#!/usr/bin/perl use strict; use warnings; my @LINE=("東京都","神奈川県","千葉県","神奈川県","東京都","埼玉県"); my %cnt; #同じキーがあれば、値が1ずつ増加していく foreach my $key (@LINE){ if ($cnt{$key}) { $cnt{$key}=$cnt{$key}+1; } else { $cnt{$key}=1; } } #カウントした回数(値)をキーとともに出力 foreach my $key (sort(keys(%cnt))){ print "$cnt{$key} $key\n"; }
結果
$perl disinct.pl 1 千葉県 1 埼玉県 2 東京都 2 神奈川県 $
処理
1. 配列、ハッシュを宣言
2. 配列要素を$keyに入れながらforeachでループさせる
3. $keyをハッシュのキーとして、if文で同じキーがあるかチェックし、ハッシュ値を増加(カウント)させる
4. 最後にハッシュ値(カウント数)をキーとともに出力させる
といったロジックになってます。
で、3.のforeach文の中でif文を用いてキーをチェックしているのが今回勉強になった点でして、例えば次のように書くと...
foreach my $key (@LINE){ $cnt{$key}=$cnt{$key}+1; }
「Use of uninitialized value within %cnt in addition (+) at disinct.pl line 12」
とwarningが出力されてしまいます。これはwaringsプラグマを付けているために出力され、「初期化されてない変数に+してるよ!」って言われています。
本当に初期化されていないかを当該の前で変数の中身をData::Dumperで見てみます。
$perl disinct.pl $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. $VAR1 = '1'; $VAR1 = '1'; $VAR1 = undef; Use of uninitialized value within %cnt in addition (+) at disinct.pl line 13. (省略)
確かに"undef"(未定義値)。つまり初期化されていないわけです。
もちろん、上記のコードでも想定の結果を得られるので、warningプラグマを外してしまえば怒られませんし、コードがすっきりするためそれはそれで良いと思います。が、warningsプラグマをはずすのは後々のメンテナスが大変になりますし、他のエラーを発見しにくくになってしまいます。きちんと回避コードを書いておくべきかと思います。
おわり。
実用perl 正規表現2 #perl
論理和と文字列クラスの扱いは、何度もはまったのでメモがてらエントリー。
内容は前回と大して変わらないのですが、今回は2パターンの文字列から日付(「DVD発売日: YYYY/MM/DD」「CD (YYYY/MM/DD)」)だけを抽出します。
入力テキスト(list.txt)
・・・
ご覧ください DVD/Blu-rayの仕様。)画面サイズ: 1.78:1ディスク枚数: 2販売元: バップDVD発売日: 2013/02/20時間: 115 分おすすめ度: 5つ星のうち 3.9 レビューをすべて見る (16件のカスタマーレビュー)16レビュー星5つ: (8)星4つ:
・・・
CD (2012/12/5)ディスク枚数: 1フォーマット: Limited Editionレーベル: SMR収録時間: 72 分ASIN: B009GN7AP0 EAN: 4988009054933 その他のエディション: CDおすすめ度: 5つ星のうち 4.5 レビューをすべて見る (18件のカスタマーレビュー)18レビュー星5つ: (13)星4つ: (3)星3つ: (1)星2つ: (0)星1つ:
・・・
※抜粋してます。
サンプルコード(parse.pl)
#!/usr/bin/perl use strict; use warnings; my $ptn_issue = qr/((.+DVD発売日:\s)|(CD\s\())(\d{4}\/\d{1,2}\/\d{1,2})([^\d{1}].+)$/x; while (<>) { chomp; my $issue = get_issue($_); print "$.: issue=$issue\n"; } sub get_issue { my $line = shift; if ($line=~/$ptn_issue/) { return $4; } else { return "does not match a pattern"; } return -1; # never comes here }
実行結果
$cat -n list.txt | cut -c-200 1 出演: 宮崎あおい, 大沢たかお, 菅原文太監督: 細田守形式: Color, Dolby, Widescreen字幕: 日本語リージョンコード: リージョンA (詳細についてはこちらをご覧ください DVD/Blu-rayの仕様。)画面サイズ: 1.78:1ディスク枚数: 2販売元: バップDVD発売日: 2013/02/20時間: 115 分おすすめ度: 5つ星のうち 3.9  レ 2 CD (2012/12/5)ディスク枚数: 1フォーマット: Limited Editionレーベル: SMR収録時間: 72 分ASIN: B009GN7AP0 EAN: 4988009054933 その他のエディション: CDおすすめ度: 5つ星のうち 4.5  レビューをすべて見る (18件のカスタマーレビュー)18レビュー星5つ:  (13)星4つ:  (3)星3つ:  ( $ $perl parse.pl list.txt 1: issue=2013/02/20 2: issue=2012/12/5 $
処理内容
前回より省略して書いてますが、処理内容はほぼ変わりません。エラー処理、ファイル処理を省略してるくらいです。正規表現定義⇒ファイル読み込み⇒1行ずつ処理⇒パターンマッチ⇒結果出力です。
正規表現
my $ptn_issue = qr/( (.+DVD発売日:\s)|(^CD\s\())(\d{4}\/\d{1,2}\/\d{1,2})([^\d{1}].+)$/x;
前回の正規表現の方法とは違うのは、論理和(or)表現"|"と、文字クラス"[]"を使用しているところです。
- "()" グループ化を意味します。括弧でくくることでマッチした部分を$1,$2,$3...と特殊変数に格納してくれます。
- "|" 論理和、orを意味します。今回は、"( (パターン1)|(パターン2))"のようにグループ2つをグループでくくることで、どちらかにマッチすれば特殊変数に格納されという表現になります。"()"外側の括弧は$1。"(パターン1)"、"(パターン2)"は$2、$3に格納されます。当然ながら、マッチしなかった特殊変数は未定義のため処理には注意が必要です。「Use of uninitialized value $3 in print at(初期化されていない値がパターンマッチで使用しちゃってるよ!)」とか出力されちゃいます。
- "[]" 文字クラスと呼ばれています。1文字の集合を表現し、"[abc]"は「a, b, c」何れか1文字を意味します。また、文字列クラスの先頭に「^」をつけると否定を表現し、"[^abc]"は「a, b, c」以外の文字を意味します。
ちなみに正規表現をためすのにhttp://regex-recipe.frozenlib.net/(参考1)のサイトが便利です。格納されている特殊変数も動的に参照できるので勉強になります。
記述省略のファイル処理
以下のようにwhile文の処理部を省略して書いています。
perlは省略して書くために特殊変数が用意されています。詳しくは説明しませんが、第7回 新人さんのための仕事で使えるPerl基礎知識(2):Perl Hackers Hub|gihyo.jp … 技術評論社(参考2)がとてもわかりやすく参考になります。因みに、今回省略している部分を省略せずに記述する以下のようになります。
省略した記述
while (<>) { chomp; my $issue = get_info($_); print "$.: issue=$issue\n"; }
省略しない記述
my $file = shift; open my $fh, "<", $file; while my $line (<$fh>) { chomp $line; my $issue = get_info($line); print "$.: issue=$issue\n"; }
参考1: 第7回 新人さんのための仕事で使えるPerl基礎知識(2)
jQuery Easing callback関数が動作しない #jQuery
jQuery Easing
jQueryではanimateという関数を使ってアニメーション効果を得ることができます。
しかし、通常、利用できるアニメーションの種類はlinerとswingの2つのみです。
そこで多くのアニメーションを実現させるためのプラグインがjQuery Easing Pluginです。
今回、このプラグインの動作を試していたところ、animate関数で渡すcallbackが正常に動作しなかったので、メモる。
jQuery Easing 実装方法
- animete(params, option)
- animate(params, [duration], [easing], [callback])
animate 日本語リファレンス
本題
日本語リファレンス1, 2を見ながら、ロールオーバーで書いてみました。
2つのコードで、1 の方は、連続動作させるとcallback関数が処理されず・・・。callback関数が呼ばれるタイミングが遅いために関数が呼ばれないまま、次の処理に移ってしまってる?ようです。一方 2 は、正常に動作します。いろいろ調べたのですが、原因不明。納得できん。。。
1.コード(抜粋)
サンプル:http://dl.dropbox.com/u/9435465/rollover_test1/t1.html
$('.boxgrid').hover( function(){ $(".cover").stop().animate( {left: "0px"}, {duration: 150,easing: "easeOutCubic"} ); }, function() { $(this).find(".cover").stop().animate( {left: "450px"}, {duration: 150, easing: "easeOutCubic", complete: function() { $(this).remove(); }} ) });
2.コード(抜粋)
サンプル:http://dl.dropbox.com/u/9435465/rollover_test1/t2.html
$('.boxgrid').hover( function(){ $(this).find(".cover").stop().animate( {left: "0px"}, 150, "easeOutCubic"); }, function() { $(this).find(".cover").stop().animate( {left: "450px"}, 150, "easeOutCubic", function() { $(this).remove(); } ); });