起動ログ

 

今回は初級編第16回 英単語の練習後編 で出てきた「ファイル操作」の知識を使って自動的に起動ログをとるプログラムを作ります。本編では「ファイルから読み込む」説明のみでしたが、ここでは「ファイルへ書き込む」処理を行います。

なお、あらかじめお断りしておきますが、今回のプログラムは今までそうだったように「評価版」(「試用版」)でも作れますが、「『評価版』では自動的にログをとるようにはできません。」。評価版でできないところは本文中に注意を書いてありますのでその都度参照してください。評価版でもプログラムを完成させることはできます。

 

1.起動ログとは?

 

起動ログ(別名、ブートログ)とは、Windowsが起動された時間などを記録するものです。これをセットしておけばWindowsが起動された時間がすべて記録に残ります。

 

2.標準モジュールの追加

 

それでは早速作りますが、今回のプログラムはWindowsが起動されたタイミングで自動的にログ(記録)をとるので一切画面に表示されません。それでフォームは必要ありません。フォームを使わないならどこにプログラムするのかと思われるかもしれませんがVBにはフォームのほかにもいろいろ用意されていて、今回は「標準モジュール」をつかいます。

フォームをなしにして標準モジュールを使用するには、まず、VBを起動したら[プロジェクト]メニューから[標準モジュールの追加]を選択します。そしてて「開く」ボタンをクリックするとModule1という名前で標準モジュールがプロジェクトに追加されます。このことは標準設定で右上の表に表示されているはずの「プロジェクトエクスプローラ」を使っても確認できます。

これで標準モジュールは追加されました。次に最初から用意されているフォームをなしにします。これにはプロジェクトエクスプローラで Form1(Form1) と書いてある部分を右クリックして 「Form1の開放」 をクリックします。

    ※プロジェクトエクスプローラがわからない人はここの画像で確認できます。

なお、プロジェクトエクスプローラが表示されていない人はキーボードの Ctrlキーを押しながら Rキー を押せば表示されます。または[表示]メニューから[プロジェクトエクスプローラ]を選択しても大丈夫です。

これで前準備は完了です。

ところで、この「標準モジュール」とは何者なのでしょうか?詳しくは初級講座本編にゆずりますが、簡単に言ってしまいますと、「表示されないフォーム」のようなものだと思っておいてください。ただ、もちろんこれは初心向けの説明で、標準モジュールにはフォームとは大きく違う重要な機能もついているということも覚えておいてください。

 

3.プログラムはどこから始まる?

 

いつもはフォームを使っているので特に気にしていないかも知れませんが、今回のようにフォームが無い場合はプログラムはどこから始まるのでしょうか? この場合は Sub Main というプロシージャから始まります。では Sub Main はどこにあるのかというと実はどこにもありません。なんと自分で書くのです。

そういうわけで、まず最初に標準モジュールに次のように記述してください。

Private Sub Main

MsgBox "プログラムが起動しました!"

End Sub

これで実行してみてください。

実行すると自動的に「プログラムが起動しました!」と表示されましたね。Sub Mainが自動的に実行されている証拠です。なお、Sub Mainがない状態でこのプログラムを実行すると「スタートアップフォーム または SubMain() が必要です。」というエラーメッセージが表示されて、その設定を行うダイアログボックスが表示されます。今回はこのダイアログボックスが表示された場合はキャンセルを押してもう一度打ち間違いがないか調べてみてください。

 

4.もう完成

 

それでは次に起動されたらファイルに日付と時間を書き込むようにします。次のようにSub Mainの内容を書き換えてください。

Private Sub Main

Open "C:\vbjhLog.txt" For Append As #1

Print #1, Now()

Close #1

End Sub

実行すると何もしないで終了するように見えますが実は C:\vbjhLog.txt というファイルにちゃんと日付と時間を記録していますね。C:\vbjhLog.txt が存在しない場合でも自動的にこのファイルを作ってくれます。

さらに、もう一度実行するとちゃんと新しい日付と時間を2行目に追加して書き込んでくれますね。For Appendと指定しているのでこのように「追加書き出し」ができるのです。この部分を For Output とすると毎回上書きされてしまって最後に起動した日時しかわかりません。(この他に、読み込み専用の For Input や、細かい処理のできる For Binary などがあります)。

ちなみに Now()関数は 日付と時間を返してくれる便利な関数です。

というわけでログとしての機能はあっさりと完成してしまいます。

 

5.自動的に実行

 

あとは、このプログラムがWindowsが起動された時に自動的に実行されるように仕込んでおけばよいのです。これにはどうするかというと、Windowsには「スタートアップ」フォルダ内にあるプログラムを起動時に自動的に実行するという機能があるのでこれを利用して、「自分のプログラム(のショートカット)をスタートアッフフォルダに作ります。」

まず、プログラムを exe 形式(実行可能形式)にする必要があるのでコンパイルします。評価版ではコンパイル機能はついていないので評価版をお使いの方はこの部分は読み流してください。

コンパイルする前に名前をつけて保存しておきましょう。標準モジュールには blog.bas、vbpファイルには pblog.vbp という名前を付けて保存してください。(保存の仕方はわかりますよね?)

保存できたらコンパイルします。[ファイル]メニューから[pblog.exe の作成]を選んでください。そして作成したい場所を選んでOKを押します。あとは自動的に pblog.exe が作成されます。

次に、スタートアップフォルダに今作った pblog.exe のショートカットを作ります。スタートアップフォルダの場所はWindowsの標準設定では C:\WINDOWS\スタート メニュー\プログラム\スタートアップ です。わからない場合は、Windowsのスタートメニューから、[プログラム]を選択して[スタートアップ]の上で右クリックして「開く」を押してください。

これで、あなたの作った pblog.exe はこれからWindowsが起動するたびに実行され C:\vbjhLog.txt には自動的に起動ログが作成されていくことでしょう。

 

以上で今回は終了ですが、さらに意欲的な方のために 起動ログをさらにパワーアップしたものに改造する方法を説明します。

 

6.ログファイル名をなんとかする

 

必ず、vbjhLog.txt にログが作成されるのは嫌だという人もいるでしょう。そういう人はプログラム中の vbjhLog.txt の部分を自分の好きなファイル名に変えればよいのですが、ログファイル名を変えるたびにプログラムを変えてコンパイルするのは面倒です。そこで、ログファイル名を自由に変える方法を紹介します。プログラムを次のように変更してください。

Private Sub Main()

Open Command For Append As #1

Print #1, Now()

Close #1

End Sub

先ほどのプログラムとほとんど変わりませんがファイル名の部分がCommand関数に置き換わっていますね?

これでコンパイルしてexeを作成したら、ショートカットを作成してください。そして、ショートカットの上で右クリックしてプロパティを選択します。そうすると リンク先 の欄に exe本体のある場所が書いてあるでしょう。たとえば、リンク先のところに次のように書いてあったとします。

"C:\vb\pblog.exe"

そうしたら、この後に、半角スペースを1つつけて作成したログファイルの名前を書いてください。たとえば、次のようにします。

"C:\vb\pblog.exe" C:\My Documents\log.txt

終わったらOKをクリックしてください。

そうすると、このショートカットが呼び出されるたびに指定したファイル(上の例ではC:\My Documents\log.txt)にログが書き込まれます。

これはショートカットのリンク先の後ろに半角スペースをいれてその後ろに書き込まれた文字は、プログラムの中でCommand関数を使うことによって取得できることを利用しています。このような文字列を「コマンドライン」または「パラメータ」、時には「引数」と呼びます。

 

7.おまけ

 

最後に、起動した時間だけではなく、起動した時のハードディスクの空き容量も記録するようにしてしまいます。このプログラムはWindowsを起動した時 ログファイルに 日付、時間、最初のドライブの空き容量、次のドライブの空き容量、…、最後のドライブの空き容量 をこの順でカンマ( , ) で区切って書き込みます。

Private Declare Function GetLogicalDriveStrings Lib "kernel32" Alias "GetLogicalDriveStringsA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Declare Function GetDriveType Lib "kernel32" Alias "GetDriveTypeA" (ByVal nDrive As String) As Long
Private Declare Function GetDiskFreeSpace Lib "kernel32" Alias "GetDiskFreeSpaceA" (ByVal lpRootPathName As String, lpSectorsPerCluster As Long, lpBytesPerSector As Long, lpNumberOfFreeClusters As Long, lpTotalNumberOfClusters As Long) As Long

Private Sub Main()

Dim FileName As String
Dim HardDiscs() As String
'ハードディスクの一覧
Dim FreeSpace As Long
Dim K As Long
Dim St As String

'▼ログファイル名の設定
If Len(Command) = 0 Then FileName = "C:\vbjhLog.txt" Else FileName = Command

'▼ハードディスクの一覧を作成し、それぞれの残り容量を計算する
HardDiscs() = GetHardDrives

For K = 0 To UBound(HardDiscs())
FreeSpace = DriveFreeSpace(HardDiscs(K)) \ 1024 \ 1024
St = St & "," & FreeSpace
Next K

'▼結果をファイルに書き出す。
Open FileName For Append As #1
Print #1, Date & "," & Time & St
Close #1

End Sub

'■ハードディスクの一覧を返す
Private Function GetHardDrives() As Variant

Dim Buffer As String * 100
Dim DriveList As String
Dim Ret As Long
Dim K As Integer
Dim TempLetter As String
Dim TempArray() As String

'有効なドライブの一覧を取得する。
Ret = GetLogicalDriveStrings(100, Buffer)

'NULLをはずす。
For K = 1 To 100

If Mid(Buffer, K, 1) <> Chr(0) Then

TempLetter = Mid(Buffer, K, 3)
K = K + 2

If GetDriveType(TempLetter) = 3 Then
DriveList = DriveList & TempLetter
End If

End If

Next K

TempArray() = Split(DriveList, ":\")
ReDim Preserve TempArray(UBound(TempArray()) - 1)
GetHardDrives = TempArray()

End Function

'■ハードディスクの空き容量を返す
Private Function DriveFreeSpace(DriveLetter As String) As Long

Dim RootPath As String
Dim SectorsPerCluste As Long
Dim BytesPerSector As Long
Dim FreeClusters As Long
Dim TotalClusters As Long
Dim DiskFreeSpace As Double
Dim DiskSpace As Double
Dim Ret As Long

RootPath = Left$(DriveLetter, 1) & ":\"

Ret = GetDiskFreeSpace(RootPath, SectorsPerCluste, BytesPerSector, FreeClusters, TotalClusters)

DiskFreeSpace = SectorsPerCluste * BytesPerSector * FreeClusters
DriveFreeSpace = CLng(DiskFreeSpace)

End Function

内容は初級編では難しいので詳しい解説はしません。特に、パソコンにあるハードディスクドライブを取得する点と、ハードディスクの空き容量を取得する点は初級者向きではありませんね。

日時を記録するのにNow()関数ではなく,Date()関数とTime()関数を使っているのは間にカンマを入れたかったからです。このように項目をカンマ区切りに、行を改行区切りにしているファイルは CSV形式と呼ばれます。CSV形式のファイルはデータを表示するのに便利で、たとえば、このログファイルの拡張子を csv に変更してExcelで開いてみると、ちゃんとデータがセルごとに表示されます。こうしておけば、ハードディスクの空き容量をグラフにするのもボタン一つというわけです。