‘Windows’ タグのついている投稿

タスクスケジューラとPHPのコンソールアプリケーション

PHP5.3+Silexを使って、Windows上で定期的に処理をするコンソールアプリケーションを作っていたのですが、タスクスケジューラが起動するタイミングで、デスクトップにコマンドプロンプトのウィンドウ(DOS窓)が表示されてしまう現象に悩んでいました。

ウィンドウを表示させない方法として、ショートカットを作成してウィンドウ最小化するという手で試してみたのですが、taskeng.exeというタイトルのウィンドウが出たままになって止まってしまう状況でした。(多分PHPファイルを引数として認識していない)

結論としては簡単で、php.exeの代わりにphp-win.exeを使うだけです。

PHP: CLI と CGI – Manual

php-win.exeはコンソールを表示させないので、これを実行ファイルとしてタスクスケジューラに登録すればOKです。

ついでにタスクスケジューラに登録する方法も書いておきます。5分おきにPHPを実行し続けるタスクをコマンドプロンプトから登録するコマンドです。最後の/Fは確認メッセージの抑制。

schtasks /create /tn "Test PHP" /tr "C:\php\php-win.exe C:\hoge\console.php args" /sc minute /mo 5 /it /F

削除はこちら。

schtasks /delete /tn "Test PHP" /f


WindowsにISC BIND9をNSISでインストールする

WindowsでDNSサーバを立てるにあたってBINDを使ったのですが、標準のBINDInstall.exeが使いにくいのと、サイレントインストールしたかったので、NSISを使ってインストーラーを作る方向にしました。

基本的には全部展開して設置したあと、VC2005再頒布可能パッケージをインストールして、named.exeをサービス登録するだけです。

ファイアウォールの許可もしています。

プラグインを3つ使っています。
Nsisunz plug-in – NSIS Zipの展開
NSIS Simple Service Plugin – NSIS サービス登録
NSIS Simple Firewall Plugin – NSIS ファイアウォール登録
Zipを二重にするのももったいないので、あらかじめ展開しておくのが妥当かとは思います。

設定ファイルは適当に作ってください。

あと肝心のBINDはこちら。
BIND | Internet Systems Consortium

!include "MUI.nsh"
!include "Sections.nsh"

!define TEMP $R0
!define TEMP2 $R1
!define VAL1 $R2
!define VAL2 $R3

Name "BIND9 Installer"
OutFile "setup.exe"

InstallDir "C:\dns"

!define BIND9_FILENAME "BIND9.8.1-P1.zip"

Section auto_setup
  
  SetOutPath "$TEMP"
  File "${BIND9_FILENAME}"
  
  SetOutPath "$INSTDIR\bin"
  nsisunz::Unzip "$TEMP\${BIND9_FILENAME}" "$INSTDIR\bin"
  
  ; VC++ 2005 redistインストール
  ExecWait '"$INSTDIR\bin\vcredist_x86.exe" /q:a /c:"VCREDI~1.EXE /q:a /c:""msiexec /i vcredist.msi /qb!"" "' 
  
  ; BINDのインストールディレクトリをレジストリに登録
  WriteRegStr HKLM "SOFTWARE\ISC\BIND" "InstallDir" "$INSTDIR"
  
  ; etcとconfに設定ファイルを配置する
  SetOutPath "$INSTDIR\conf"
  File /r "conf\*.txt"
  
  SetOutPath "$INSTDIR\etc"
  File "named.conf"
  ExecWait '"$INSTDIR\bin\rndc-confgen" -a -b 512'
  
  ; Firewall許可
  SimpleFC::AddApplication "ISC BIND" "$INSTDIR\bin\named.exe" 0 2 "" 1
  
  ; BINDをサービスに登録
  SimpleSC::InstallService "BIND" "ISC BIND" "16" "2" "$INSTDIR\bin\named.exe" "" "NT AUTHORITY\NetworkService" ""
  
  ; BINDサービス起動
  SimpleSC::StartService "BIND" "" 30

SectionEnd

Section "Uninstall"
  
  ; サービス停止と解除
  SimpleSC::StopService "BIND" 1 30
  SimpleSC::RemoveService "BIND"
  
  ; レジストリ削除
  DeleteRegKey HKLM "SOFTWARE\ISC\BIND"
  
  ; Firewall解除
  SimpleFC::RemoveApplication "$INSTDIR\bin\named.exe"
  
  ; ファイル削除
  RMDir /r "$INSTDIR"
  
SectionEnd


Windows版MySQLの配布形態ごとの違い

Windows版のMySQL Server 5.5には、3種類の配布形態があります。

MySQL Installer

http://www-jp.mysql.com/downloads/installer/
msi形式のファイルです。
mysql-installer-5.5.21.0.msiのようなファイル名になっています。

サーバーに加えて、サンプルとドキュメント、Connectors、Workbenchなどのツールが含まれます。一番多くの人におすすめできるパッケージとの事。

The Complete Package

http://www-jp.mysql.com/downloads/mysql/
WS000006

上2つがComplete Packageです。mysql-5.5.21-win32.msiのようなファイル名になっています。組み込みサーバやベンチマークスイートなどが含まれます。

The Noinstall Archive

Complete Packageと同じURLで配布されています。上の画像では、Zip Archiveと書かれているもののうち、上2つです。mysql-5.5.21-win32.zipのようなファイル名になっています。

ファイルサイズが大きいのは、テストやベンチマークなどに加えて、デバッグ情報(pdb:プログラムデバッグデータベースファイル)が付属しているためです。

ただし、このzipファイルにはMySQLInstanceConfig.exeは含まれていません。my.iniファイルの作成とサービス登録は自力で行う必要があります。

ちなみに最後のひとつはソースコードです。バイナリは含まれていません。

それぞれのパッケージのインストール方法と、インストーラーの挙動はpdfで公開されています。
http://downloads.mysql.com/docs/mysql-windows-excerpt-5.5-en.pdf

表です。5.1のEssentialsを参考にしているので間違っているかもしれません。
出典:http://downloads.mysql.com/docs/mysql-windows-excerpt-5.1-en.pdf

 

Installer

Complete

No-install

Installer

あり

あり

なし

MySQL Server Instance Config Wizard

あり

あり

なし

Test Suite

なし

あり

なし

MySQL Server

あり

あり

あり

MySQL Client Programs

あり

あり

あり

C Headers/Libraries

あり

あり

あり

Embedded Server

なし

オプション

あり

Scripts and Examples

なし

オプション

あり

5.1まであった、Essentialsはなくなったようです。

MySQLのmsi形式のインストーラーは、別のMySQLInstaller.exeを展開して使うためにあるようなものなので、インストール先ディレクトリをmsiexecを使ったコマンドラインで指定したりできません。

NSISなどに組み込んで、インストール先を指定したい場合はzipで配布されているNo-install版を使うのが正しいようです。


Windows版のPHP5.3がc0000005で強制終了する

Symfony 1.4.16をWindowsのPHP 5.3.9で実行したときに、特定の条件で強制終了する現象に悩まされていました。
主にSymfonyタスクでdoctrine:data-dumpなどを実行するときに落ちていました。

色々調べた結果、Symfonyに問題があるわけではなく、/lib/vendor/symfony/lib/config/sfDefineEnvironmentConfigHandler.class.phpがきっちり4096バイトだったということが原因でした。

つまり、PHP5.3.9では、4096バイトのファイルをrequireもしくはincludeするとc0000005(Access Violation)で強制終了します。CLIに限らず、Apache経由でも同じです。

試しに4096バイトの一切コードが書かれていないテキストファイルを作ってrequireしてみると、再現しました。

強制終了時のウィンドウと、内容は以下のとおり。

image

ちなみにモジュール名はnts(Non Thread Safe)版ならphp5.dll、ts(Thread Safe)版ならphp5ts.dllです。
どちらも確認しましたが、どちらも同じ現象です。モジュールは入っていても入っていなくても同じです。

問題の署名:
  問題イベント名:    APPCRASH
  アプリケーション名:    php.exe
  アプリケーションのバージョン:    5.3.9.0
  アプリケーションのタイムスタンプ:    4f0c5cd0
  障害モジュールの名前:    php5.dll
  障害モジュールのバージョン:    5.3.9.0
  障害モジュールのタイムスタンプ:    4f0c5dfb
  例外コード:    c0000005
  例外オフセット:    00090f5b
  OS バージョン:    6.1.7601.2.1.0.256.48
  ロケール ID:    1041
  追加情報 1:    0a9e
  追加情報 2:    0a9e372d3b4ad19135b953a78882e789
  追加情報 3:    0a9e
  追加情報 4:    0a9e372d3b4ad19135b953a78882e789

多分現象はこのバグ報告と同じだと思います。
PHP :: Bug #60758 :: require() crashes Apache

5.4.0RC5でも解決してないみたいですね。報告とほぼ同じですが、これで再現できます。

<?php
file_put_contents('test.txt', str_pad('', 4096));
include('./test.txt');

とりあえず対処法としては改行1文字でも増やしておけばいいってことですか…


nginxのWindows版バイナリをビルドする

nginxのWindows版バイナリは公式で配布されていますが、nginxに追加のモジュールを入れたい場合、どうしても自分でビルドする必要がでてきます。

ビルド方法は公式のドキュメントに書かれています。

How to build nginx on the Win32 Platform with Visual C

が、色々ハマるのでメモしておきます。ビルド環境はWindows7 Professional x64です。

必要なのは以下。

  • Microsoft Visual C++ Compiler
  • Microsoft Windows SDK
  • MinGW/MSYS
  • ActivePerl
  • PCRE
  • zlib
  • OpenSSL

まず、VCコンパイラが必要なので、Microsoft Visual C++ Expressをインストールします。

Microsoft Visual Studio Express

上記ページのVisual C++ 2010 ExpressのWebインストールをクリックすればvc_web.exeがダウンロードできるので、それを実行してあとは言われるままにインストールすればOKです。

続いてMicrosoft Windows SDK(旧Platform SDK)をインストールします。

Windows SDK: Download the Windows SDK for Windows 7 and More | MSDN

「Install Now」を押せばインストールできます。こちらもそのままインストールすればOK。

OpenSSLのコンパイルにPerlが必要なので、ActivePerlをインストールします。32bit版と64bit版がありますが、僕は64bit版をインストールしました。

ActivePerl Downloads – Perl Binaries for Windows, Linux and Mac | ActiveState

続けてMinGW/MSYSのインストールをします。

MinGW – Minimalist GNU for Windows – Browse Files at SourceForge.net

「Looking for the latest version?」と書かれている隣のファイルをダウンロードします。

インストールが終わったら環境変数の設定をします。

MinGW Shellを起動して、パスを設定します。

$ export LIB="C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\lib;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Lib"
$ export INCLUDE="C:\\Program Files (x86)\\Microsoft Visual Studio 10.0\\VC\\include;C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1\\Include"
$ export PATH="$PATH:/c/Perl64/bin:/c/Program Files (x86)/Microsoft Visual Studio 10.0/VC/bin:/c/Program Files (x86)/Microsoft Visual Studio 10.0/Common7/IDE:/c/Program Files/Microsoft SDKs/Windows/v7.1/Bin"

nginxのソースコードをダウンロードしましょう。tarボールで提供されているものには、Windows用のConfigureが入っていないらしいので、svnから取得します。

svnコマンドが使えるのであれば、
svn co svn://svn.nginx.org/tags/release-(バージョン番号)
でチェックアウトできます。僕はrelease-1.0.10を使いました。

なぜかTortoiseSVNではtags/release-1.0.10が表示できませんでした。

ダウンロードしたソースコードはMSYSのHOMEディレクトリに置きます。

C:\MinGW\msys\1.0\home\(ユーザー名)\nginx
としました。

PCRE、zlib、OpenSSLをダウンロードします。

PCRE – Browse /pcre at SourceForge.net

zlib Home Site

OpenSSL: Source, Tarballs

pcre-8.20.zip、zlib-1.2.5.tar.gz、openssl-1.0.0e.tar.gzをダウンロードしました。

nginxディレクトリの下にobjs/libディレクトリを作成します。ここに、先ほどダウンロードした3ファイルを解凍したものを設置します。

これで準備はできたので、ビルドします。

公式のビルド方法に載っているConfigureを実行します。が、PCREのバージョンは8.20になっていたので、–with-pcreの引数は変更します。あとは適宜合わせてください。

$ auto/configure –with-cc=cl –builddir=objs –prefix= \
–conf-path=conf/nginx.conf –pid-path=logs/nginx.pid \
–http-log-path=logs/access.log –error-log-path=logs/error.log \
–sbin-path=nginx.exe –http-client-body-temp-path=temp/client_body_temp \
–http-proxy-temp-path=temp/proxy_temp \
–http-fastcgi-temp-path=temp/fastcgi_temp \
–with-cc-opt=-DFD_SETSIZE=1024 –with-pcre=objs/lib/pcre-8.20 \
–with-zlib=objs/lib/zlib-1.2.5 –with-openssl=objs/lib/openssl-1.0.0e \
–with-select_module –with-http_ssl_module –with-ipv6

Configureが成功したら、nmakeでビルドします。

$ nmake -f objs/Makefile

これで、何も問題がなければnginx/objsディレクトリにnginx.exeファイルが出来上がっているはずです。

このnginx.exeファイルを、ひとつ上のディレクトリ(nginx)に設置して、

$ mkdir logs
$ mkdir temp

として、

$ start nginx.exe

で起動できます。

これでやっと追加モジュールをインストールできるというもの。


今日の微妙エラー

コントロールはひとつの case ラベル (‘default:’) から別のラベルへ流れ落ちることはできません。

switch (message)
{
    case "hoge":
        funcA();
        break;
    default:
        funcB();
        break; // これがないとエラー
}

他の言語のクセでbreak書かなかったら起きた。

「フォールスルー」ってことなんですね。

ちなみにcaseのあとのブロックにコードを書かなければフォールスルーはできるという話。


Pythonのwin32comからSilverlightを使おうと試みる

最終的にはPythonで書かれたWindowsアプリケーションで、Silverlightのコンテンツをロードしたいという目的なのですが、とりあえずSilverlightのActiveXコントロールを読み込んで動作を確認してみたいので色々実験。

まず、インストールされているSilverlightのバージョンを調べてみる。

Javascriptで書かれたコードがいくつか見つかったのでそれを書き直す。

以下はJS版。

var control = new ActiveXObject('AgControl.AgControl');
alert(control.IsVersionSupported('3.0'));

これをPythonで書いてみる。

import win32com.client
control = win32com.client.Dispatch("AgControl.AgControl")
print control.IsVersionSupported('3.0')

Silverlight 3がインストールされていればTrueが表示されます。

他にどんなメソッドが定義されているのかを調べるために、Visual StudioからAgControlを参照して、オブジェクトブラウザで調査。

というか、Silverlightのプラグインのリファレンスがあった。

Silverlight プラグインのオブジェクト リファレンス

が…Sourceを指定してもIsLoadedプロパティがTrueにならない…うーん…もう少し調べてみる。


PythonでMIDI出力をしてみる

既存のPythonで作ったWindowsアプリケーションにMIDI出力を組み込む用事があったので、実験してみました。

参考サイトはこちら。

sulume blog» ブログアーカイブ » python で MIDI を使う

MIDIIO.dllというのはおーぷんMIDIぷろじぇくとで公開されているMIDIメッセージ入出力用ライブラリです。

これもダウンロードして、pyファイルと同じ場所に置いておきます。

で、ソースコードはこちら。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

c_mess = ctypes.create_string_buffer(3)
c_mess.value = '\x90\x3C\x64'

midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)

time.sleep(3)

midiiolib.MIDIOut_Close(midiout)

説明することもあまりないですが、8行目のMIDIOut_GetDeviceNameで、MIDI出力の先頭のデバイスの名前を先に取得します。

で、その名前を使ってMIDIOut_Openで出力デバイスを開きます。

11~12行目ではノートを作成します。とりあえずドの音でも鳴らしておきます。この辺もMIDIIO.dllに入っていたドキュメントのサンプルと同じ。

あとはMIDIOut_PutMIDIMessageで出力するだけです。

ちゃんと閉じておかないと、次回音が鳴らなかったりする(オープンに失敗します)ので、MIDIOut_Closeで閉じておきましょう。

実験として、ちょっと長いデータを指定してみる。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

notes = ['\x90\x3C\x64',
         '\x90\x3E\x64',
         '\x90\x40\x64',
         '\x90\x41\x64',
         '\x90\x43\x64',
         '\x90\x45\x64',
         '\x90\x47\x64',
         '\x90\x48\x64']

c_mess = ctypes.create_string_buffer(3)

for note in notes:
    c_mess.value = note

    midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)
    time.sleep(0.5)

time.sleep(1.0)

midiiolib.MIDIOut_Close(midiout)

和音を鳴らしてみるテスト。

import ctypes
import time

midiiolib = ctypes.windll.LoadLibrary(r".\MIDIIO.dll")

c_deviceName = ctypes.create_string_buffer(32)

midiiolib.MIDIOut_GetDeviceName(0, c_deviceName, 32)
midiout = midiiolib.MIDIOut_Open(c_deviceName.value)

notes = ['\x90\x3C\x64',
         '\x90\x40\x64',
         '\x90\x43\x64']

c_mess = ctypes.create_string_buffer(3)

for note in notes:
    c_mess.value = note

    midiiolib.MIDIOut_PutMIDIMessage(midiout, c_mess.value, 3)

time.sleep(3.0)

midiiolib.MIDIOut_Close(midiout)

とりあえずこれだけできれば満足なので終了。


ネットワークドライブからデータを全部バックアップする

TeraStationのHDDが1台故障したので、交換を前に中身を全部バックアップする必要がありました。

ちなみに以前同じような症状でRAID崩壊させたことがあるので今回は慎重に…

共有フォルダのルートがたくさんあるので、それをいかに簡単にコピーするかがキモ。

共有フォルダ自体はコピーしようとドラッグアンドドロップすると、ショートカットが作られてしまう。

やりたいことは、PCを使ってLAN内のNASからデータを全部コピーして、ローカルに接続してあるUSB HDDにバックアップすること。

で、robocopyコマンドというのが便利っぽいので使ってみた。使ったOSはWindows Vista。標準コマンド?

まずは対象のフォルダ名一覧の取得から。

C:\> net view \\NAS

みたいにすると、フォルダ一覧が文字情報として取れます。

で、robocopy。

robocopyでフォルダをバックアップ/同期させる - @IT

どうやらrsyncみたいに使えるよう。

C:\> robocopy /mir \\NAS\dir1 C:\Backup\dir1

という感じで書けば対象ディレクトリの中身をミラーリングコピーしてくれます。

ちなみに受け側ディレクトリは作っておかなくても勝手に作ってくれます。

というわけで、先ほどのnet viewの結果を流し込んだコマンドリストを作ってbatファイルに保存して、実行。

全部きれいにバックアップできました。

今xcopyって推奨されてないんですね。知らなかった。


NSISから使える、起動中のプロセスを削除するプラグイン

常駐アプリケーションを作ったはいいが、アンインストールしようとしたときにプロセスが起動していると、削除できなくて困る。

というわけで、プロセスを殺す目的のプラグインDLLを作成。コンパイル済みファイルはエントリの最後に。

taskkillコマンド使えという話ですが、Windows XP Home Editionにはtaskkillコマンドが含まれていないので。

今回もさっくりC#で。C#.NETで作ってしまうと、そのままではNSISで使えないのだけど、.NETで作ったDLLをNSISのプラグインとして使う方法は以下のエントリを参照。

NSISで、C#で書かれた自作のDLLを使う : blog.loadlimit – digital matter –

ソースは以下。C#でクラスライブラリとしてプロジェクトを作成。プロセス名を指定すると、マッチしたプロセスを全部終了してくれます。

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace TaskKill
{
    public class TaskKill
    {
        [DllImport("Psapi.dll", SetLastError = true)]
        static extern bool EnumProcesses(
           [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U4)] [In][Out] UInt32[] processIds,
             UInt32 arraySizeBytes,
             [MarshalAs(UnmanagedType.U4)] out UInt32 bytesCopied
          );

        [DllImport("kernel32.dll")]
        static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle,
           uint dwProcessId);

        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VMOperation = 0x00000008,
            VMRead = 0x00000010,
            VMWrite = 0x00000020,
            DupHandle = 0x00000040,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            Synchronize = 0x00100000
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool CloseHandle(IntPtr hObject);

        [StructLayout(LayoutKind.Sequential)]
        public struct StringBuffer
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
            public string text;
        }

        [DllImport("psapi.dll")]
        private static extern bool EnumProcessModules(IntPtr hProcess, out IntPtr lphModule, int cb, out int lpcbNeeded);
        [DllImport("psapi.dll")]
        private static extern int GetModuleBaseName(IntPtr hProcess, IntPtr hModule, out StringBuffer lpBaseName, int nSize);

        [DllImport("kernel32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        static extern bool TerminateProcess(IntPtr hProcess, int uExitCode);

        public static void KillByName(string pname)
        {

            UInt32 arraySize = 1024;
            UInt32 arrayBytesSize = arraySize * sizeof(UInt32);
            UInt32[] processIds = new UInt32[arraySize];
            UInt32 bytesCopied;

            bool success = EnumProcesses(processIds, arrayBytesSize, out bytesCopied);

            if (!success)
            {
                return;
            }
            if (0 == bytesCopied)
            {
                return;
            }

            UInt32 numIdsCopied = bytesCopied >> 2;

            if (0 != (bytesCopied & 3))
            {
                UInt32 partialDwordBytes = bytesCopied & 3;

                return;
            }

            for (UInt32 index = 0; index < numIdsCopied; index++)
            {
                IntPtr hProcess = OpenProcess(
                    ProcessAccessFlags.QueryInformation | ProcessAccessFlags.VMRead | ProcessAccessFlags.Terminate,
                    false,processIds[index]);
                if (hProcess.ToInt32() != 0)
                {
                    IntPtr hMod = IntPtr.Zero;
                    int cbNeeded;
                    StringBuffer szProcessName;
                    szProcessName.text = "<unknown>";

                    if (EnumProcessModules(hProcess, out hMod, Marshal.SizeOf(hMod), out cbNeeded))
                    {
                        GetModuleBaseName(hProcess, hMod, out szProcessName, Marshal.SizeOf(szProcessName));
                    }

                    if (szProcessName.text == pname)
                    {
                        TerminateProcess(hProcess, -1);
                    }

                    CloseHandle(hProcess);
                }
            }

        }

    }
}

で、これをNSISの配布ファイルに含めておいて、

; アンインストーラ
Section "Uninstall"
  ; アンインストールで使用するプラグインの準備
  InitPluginsDir
  SetOutPath $PLUGINSDIR
  File "TaskKill.dll"

  ; hogehoge.exeが起動していたら、それを落とす
  CLR::Call /NOUNLOAD "TaskKill.dll" "TaskKill.TaskKill" "KillByName" 1 "hogehoge.exe"

  ; インストールしたファイル群削除
  Delete $INSTDIR\*.*

  CLR::Destroy
SectionEnd

という感じでnsiファイルを記述。

ファイルは下記リンクからダウンロードしてお使いください。

download TaskKill.dll