bigLiBox

備忘録だったり。読書メモだったり。ところで仕事が終わりそうにないんですが。

Windows7のCドライブ容量が減らない。減らせない(使用済みの容量がファイル容量と一致しない)時

SSD 225GBをCドライブとして割り当ててたが、容量がぱっつぱつになった。
空き容量300MBくらいしかない。。。
しかし、Cドライブ以下のシステムファイルや隠しファイルを全て表示してプロパティを見ても合計で80GBくらいしかない。

まずこれを基に確認してみた。
「知恵ノート」は終了いたしました - Yahoo!知恵袋

「System Volume Information」は、「システムの復元機能(復元ポイント)」と、「以前のバージョン機能」が使用するための隠し領域です。ここに大量のデーターが保存されるとエクスプローラーには表示されないのに、システムドライブ(C)使用容量が増えることになります。

とのことなので、

  1. 隠しフォルダを表示
  2. 「System Volume Information」フォルダのアクセス権を得る

で「System Volume Information」の容量を確認したが16GBくらいしかない。

次にこれを基に確認してみた。
Cドライブの空き領域の表示がおかしい!? -128GBのSSDをCドライブに使- Windows 7 | 教えて!goo
私とほぼ同じ状況の人っぽい。

そこで、ディレクトリの容量表示ツール「FileSum」をダウンロード。
http://www.vector.co.jp/soft/winnt/util/se513257.html
管理者権限で実行してみたところ
「C:\Windows\Temp」の容量が160GBくらいあった!

WindowTempフォルダには「cab_XXX_X」というファイルが大量にあり
それが容量160GBの大部分を占めていた。

そこでコレ。
C:WindowsTemp フォルダーに cab_XXX_X ( X は数字) が生成されディスクの容量を圧迫している場合の対処方法

C:\Windows\Temp\cab_XXX_X は、Windows Module Installer Service によって利用される、CBS.log を圧縮する際に利用される一時ファイルとなります。
このファイルは、本来圧縮完了後削除されるはずですが、圧縮時の処理の中で問題が発生した場合、残存することがございます。

対処方法:
以下のファイルを別の場所に移動するもしくは削除します。

C:\Windows\temp\cab_XXX_X (前述の図)
C:\Windows\logs\CBS\CbsPersist_xxxxxxxxxxx.log (以下図)
C:\Windows\logs\CBS\CbsPersist_xxxxxxxxxxx.cab (以下図)

とな。
とりあえずWindowsTempフォルダしたの「cab_XXX_X」ファイルを削除してよさそうなので、全て削除で。
無事Cドライブの空き容量確保!
f:id:bigLiBox:20160929131803p:plain

しかしながら「cab_XXX_X」ファイルが増え続けることの根本解決には至ってない。

DataTableのカラム名(ColumnName)をEnumで定義し、DataTableに列(DataColumn)を追加する

コードマスタの情報をCSVファイルに定義しておいて、
CSVファイルを読込んでDataTable型でファイル内容を取得し保持したりすることがある。

そこでDataTableのカラム名を列挙したEnumと、ファイル内容を保持するメンバ変数を定義しておいて、

#Region "Enum"
    ''' <summary>
    ''' マスタテーブル項目
    ''' </summary>
    Enum MasterTableColumn As Integer
         Code
         Meishou
         Ryakushou
    End Enum
#End Region

#Region "メンバ変数"
    ''' <summary>
    ''' マスタテーブルデータ
    ''' </summary>
    Private masterTableData As DataTable
#End Region

メンバ変数を初期化する時に、以下のようにDataTableにEnumのメンバー分、DataColumを追加するコードを書いてた。

'メンバ変数の初期化
Me.masterTableData = New DataTable()
Me.masterTableData.Columns.Add(New DataColumn(MasterTableColumn.Code.ToString(), GetType(String)))
Me.masterTableData.Columns.Add(New DataColumn(MasterTableColumn.Meishou.ToString(), GetType(String)))
Me.masterTableData.Columns.Add(New DataColumn(MasterTableColumn.Ryakushou.ToString(), GetType(String)))

でも正直こんなの書くのカラム3個くらいが限界。と思ってたけど、
[列挙体の一覧を foreach を使って取得する方法]とやらを使えば、簡単かも。

Me.masterTableData = New DataTable()
For Each val As MasterTableColumn In [Enum].GetValues(GetType(MasterTableColumn))
    Me.masterTableData.Columns.Add(New DataColumn(val.ToString(), GetType(String)))
Next

すごくスッキリ。
問題は、これ実際に意図した通りに動作するのかまだ検証してないことだな。


参考:

DataGridViewの列幅を内容に合わせ、かつ最後の列はコントロール幅に合わせる

以下のようなDataGridViewを表示したい。

  1. 列幅は可変
  2. 初期表示時の列幅はヘッダーセルを含むすべてのセルの内容に合わせて調整する
  3. セルの内容に合わせた時、すべての列を合わせた幅がDataGridViewの幅(垂直スライドバーの部分除く)より短い場合、背景色見えるのかっこ悪いので最後の列の幅を広げて調整する(※でもその列も表示した後は列幅可変)
  4. すべての列がReadOnly

f:id:bigLiBox:20160928185235p:plain

3.の条件を実現するのがなんかややこしかった。

'日時
Dim txtDataTime As New DataGridViewTextBoxColumn()
txtDataTime.HeaderText = "日時"
txtDataTime.Name = "txtDataTime"
txtDataTime.ReadOnly = True
dgvInformation.Columns.Add(txtDataTime)

'メッセージID
Dim txtMessageID As New DataGridViewTextBoxColumn()
txtMessageID.HeaderText = "メッセージID"
txtMessageID.Name = "inputDataCheckInfo_MessageID"
txtMessageID.ReadOnly = True
dgvInformation.Columns.Add(txtMessageID)

'行
Dim txtColumn As New DataGridViewTextBoxColumn()
txtColumn.HeaderText = "行"
txtColumn.Name = "txtColumn"
txtColumn.ReadOnly = True
dgvInformation.Columns.Add(txtColumn)

'列
Dim txtRow As New DataGridViewTextBoxColumn()
txtRow.HeaderText = "列"
txtRow.Name = "txtColumn"
txtRow.ReadOnly = True
dgvInformation.Columns.Add(txtRow)

'メッセージ
Dim txtMessage As New DataGridViewTextBoxColumn()
txtMessage.HeaderText = "メッセージ"
txtMessage.Name = "txtMessage"
txtMessage.ReadOnly = True
dgvInformation.Columns.Add(txtMessage)

'ユーザーが列の幅を変更できる
dgvInformation.AllowUserToResizeColumns = True

Dim index As Integer

dgvInformation.Rows.Add()
index = dgvInformation.RowCount - 1
dgvInformation.Rows(index).Cells(0).Value = "2016/07/13 11:43:26"
dgvInformation.Rows(index).Cells(1).Value = "E0001"
dgvInformation.Rows(index).Cells(2).Value = "2"
dgvInformation.Rows(index).Cells(3).Value = "列番号4"
dgvInformation.Rows(index).Cells(4).Value = "必須項目が入力されていません。"

dgvInformation.Rows.Add()
index = dgvInformation.RowCount - 1
dgvInformation.Rows(index).Cells(0).Value = "2016/07/13 11:43:26"
dgvInformation.Rows(index).Cells(1).Value = "E0001"
dgvInformation.Rows(index).Cells(2).Value = "3"
dgvInformation.Rows(index).Cells(3).Value = "列番号1"
dgvInformation.Rows(index).Cells(4).Value = "必須項目が入力されていません。"

dgvInformation.Rows.Add()
index = dgvInformation.RowCount - 1
dgvInformation.Rows(index).Cells(0).Value = "2016/07/13 11:43:26"
dgvInformation.Rows(index).Cells(1).Value = "E0002"
dgvInformation.Rows(index).Cells(2).Value = "3"
dgvInformation.Rows(index).Cells(3).Value = "列番号8"
dgvInformation.Rows(index).Cells(4).Value = "半角英数字以外の文字が入力されています。"

'一旦、列幅をヘッダーセルを含む列内のすべてのセルの内容に合わせて調整
dgvInformation.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)

'表示列の幅を取得する
Dim allWidth As Integer = dgvInformation.Columns.GetColumnsWidth(DataGridViewElementStates.Visible)

If allWidth <= dgvInformation.Width - SystemInformation.VerticalScrollBarWidth Then
    '表示されているすべての列幅がデータグリッドビュー幅より狭い場合、最後の列幅を広げる
    dgvInformation.Columns.GetLastColumn(DataGridViewElementStates.Visible, Nothing).Width =
        dgvInformation.Width -
        (allWidth -
        dgvInformation.Columns.GetLastColumn(DataGridViewElementStates.Visible, Nothing).Width +
        SystemInformation.VerticalScrollBarWidth)
End If

とりあえず時間ないのでコードだけ記録。

ちなみに列幅がDataGridViewの幅を超える場合は最後の列の幅はセル内容に合わせた幅になる。
f:id:bigLiBox:20160928190806p:plain

参考:

エクセルのシート名一覧を取得する

詳細設計書とかシートが大量にあるExcelを作って
そのシート名を基に一覧つくるとか多々あるのでとっても便利。

  1. ALT+F11でVisual Basic Editorを起動する
  2. イミディエイトウインドウが表示されていない場合は[Ctrl+G]キー押下
  3. イミディエイトウィンドウに以下を入力し、[Enter]キー押下
For Each i In ThisWorkbook.Sheets: debug.print i.name : next i

⇒下にシート名一覧が表示される
 (ただし、非表示シートも表示されるよ)

参考:

ビルド時に空のフォルダを出力ディレクトリに作る

[プロジェクトのプロパティ/コンパイル/ビルドイベント]を選択し、

ビルド後イベントのコマンドラインディレクトリ作成のコマンドを記述する。

ディレクトリ作成のコマンド形式

md ((drive) path) [directory name]

ただし、ディレクトリ作成のコマンドだけでは繰り返しビルドを行った際、すでに出力ディレクトリに同名のフォルダが存在する場合がある。

そのため、同名ファイルが存在してエラーが発生しても無視する(終了コード0で終了する)ように以下のようなコマンドにした。

md "hoge" > NUL 2>&1

if ERRORLEVEL 1 cmd /c exit 0


参考: