🔍 きっかけ:インストール不要で業務に役立つツールを届けるには?
■ 背景:業務に活かしたいフリーウェアの存在
近年、便利なフリーウェアが数多く公開されており、業務効率化や個人の作業支援に役立つものも少なくありません。
「これが会社でも使えたら」と思う場面は、誰しも一度は経験しているはずです。
■ 制約:企業端末へのインストールの壁
しかし、たとえ著作権的に問題のないフリーウェアであっても、企業の端末にインストールするには申請が必要です。
特に、ランサムウェアなどのセキュリティリスクが高まる昨今、インストール制限や外部サイトへのアクセス制限は多くの企業で常態化しています。
- オンラインストレージ(Google Drive、Dropboxなど)の利用禁止
- 外部サイトへのアクセス制限
- 管理者権限がない端末でのインストール不可
■ 発想転換:インストールできないなら、ビルドしてしまえばいい
この制約を逆手に取り、次のような発想に至りました。
「インストールが難しいなら、ソースコードを持ち込んで、自分でビルドすればいいのでは?」
この方法なら、インストール不要・ログイン不要・申請不要で、業務に役立つツールを導入できます。
■ 技術的根拠:Windows標準環境で完結するC#ビルド
Windowsには、以下の環境がプレインストールされています。
- .NET Framework(v4.0以降)
- C#コンパイラ(
csc.exe) - PowerShell(スクリプト実行環境)
これらを活用すれば、Visual Studioを使わずに、複数の .cs ファイルをマージしてビルドすることが可能です。
■ 実装方針:コピペ1回で済む配布形式へ
- ソースコードを1枚にマージし、ブログ記事1つにまとめる
- コピペ1回で
.csファイルを取得できるようにする - PowerShellスクリプトとバッチファイルで、ビルド処理を自動化
これにより、「持ち込み=コピペ」だけで済む配布形式が実現します。
■ 展望:思想とセキュリティの両立
この仕組みは、技術的にはシンプルで、誰でも思いつく内容です。
しかし、実際に運用されていないのは、「思想としての配布設計」がなされていなかったからだと考えています。
- ソースコードの透明性を保ちつつ、悪意あるコードの持ち込みを防ぐ
- 履歴と構造を残すことで、思想の痕跡を共有する
- インストール不要の配布形式として、社内でも安心して使える
この仕組みが、業務と好奇心の交差点にある「やりたいことの芽」を育てる土壌になることを願っています。
✅ できること
- 同一フォルダ内の
.csファイルをすべて読み込み、usingを先頭に統合し、1枚の.csにマージ - マージされた
.csファイルを、Windowsにプレインストールされているcsc.exe(C#コンパイラ)でビルド - EXEファイルを生成し、配布可能な形に
- ログファイルに履歴を記録(成功・失敗・タイムスタンプ)
📦 設置方法
- Visual Studioで作成した
.csファイル(Main.cs,Form1.Designer.csなど)を1つのフォルダにまとめる - 以下の PowerShell スクリプト(例:
MyApp.ps1)を同じフォルダに保存 - 以下のバッチファイル(例:
MyApp.bat)を同じフォルダに保存
※ マージ&ビルドのスクリプトでは、スクリプトやバッチファイルと同一のフォルダだけでなく、サブフォルダの.csも拾い集めるため、マージしたい.csが1プロジェクトで完結している場合は、プロジェクトフォルダ直下に保存してしまえばいい。
✅ このビルドシステムでの推奨設定
| ファイル種別 | 推奨エンコード | メモ帳での選択名 | 理由 |
|---|---|---|---|
.bat(バッチ) |
UTF-8(BOMなし) | UTF-8 | BOMがあると powershell コマンドが誤動作することがあるため |
.ps1(PowerShell) |
Shift_JIS または UTF-8(BOMなし) | ANSI または UTF-8 | SJISは日本語環境で安定。UTF-8(BOMなし)でもOKだが、環境によっては文字化け注意 |
▶ 使用方法
MyApp.batをダブルクリック(または Visual Studio のビルド後イベントで呼び出す)MyApp_Merged.csが生成され、MyApp.exeがビルドされるMyApp_BuildLog.txtに履歴が記録される
🔧 応用的な使い方
Visual Studio の「ビルド後イベント」に
.batを登録することで、IDEとPowerShellの同期的共存が可能この仕組みは、Visual Studio(IDE)とPowerShellスクリプトが役割分担しながら連携する構造を持っています。
IDEで開発・編集を行いながら、ビルド後に自動でマージ・配布用ビルドが実行されることで、開発と配布用ファイルの作成が同時に進行します。処理の流れ(例:
MyApp.batを使用)MyApp.batとMyApp.ps1を任意の同一フォルダに配置- Visual Studioで「ビルド後イベント」から
MyApp.batを起動する設定をする - Visual Studioでプロジェクトをビルド
- ビルド成功後、「ビルド後イベント」から
MyApp.batを起動 MyApp.batが同一フォルダ内の同名のMyApp.ps1を起動- PowerShellが、ビルド済みの
.csファイル群を1枚にマージ - マージされたソースコードを再度ビルドし、EXEファイルを生成
- マージ後のコードでもビルドが通ることが確認され、配布可能な状態が完成
Merged.csを配布用に整形・署名・圧縮することで、社内配布・教育用途にも展開可能。1ファイルであるため配布が容易。usingの統合やファイル名コメントにより、履歴と構造の痕跡を残す思想的配布が可能。単純にマージするだけでは、usingが複数定義されていることによりコンパイルエラーとなる。
📜 ソースコード(PowerShell:MyApp.ps1)
$scriptName = [System.IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Path)
$folder = Split-Path -Parent $MyInvocation.MyCommand.Path
$mergedPath = Join-Path $folder "${scriptName}_Merged.cs"
$exePath = Join-Path $folder "$scriptName.exe"
$logPath = Join-Path $folder "${scriptName}_BuildLog.txt"
$csFiles = Get-ChildItem -Path $folder -Filter *.cs | Sort-Object Name
$fx = Join-Path $env:WINDIR 'Microsoft.NET\Framework64\v4.0.30319'
if (!(Test-Path $fx)) {
$fx = Join-Path $env:WINDIR 'Microsoft.NET\Framework\v4.0.30319'
}
$csc = Join-Path $fx 'csc.exe'
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Add-Content -Path $logPath -Value "`n[$timestamp] using統合+ビルド開始:$scriptName.exe"
try {
if ($csFiles.Count -eq 0) { throw "C#ファイルが見つかりません。" }
if (Test-Path $mergedPath) { Remove-Item -Path $mergedPath -Force }
$usingLines = @()
$bodyLines = @()
foreach ($file in $csFiles) {
$lines = Get-Content -Path $file.FullName
$bodyLines += "`n// --- ファイル: $($file.Name) ---`n"
foreach ($line in $lines) {
if ($line.Trim().StartsWith("using ")) {
$usingLines += $line
} else {
$bodyLines += $line
}
}
}
$usingLines = $usingLines | Sort-Object -Unique
$finalLines = @()
$finalLines += "// === using統合ファイル:${scriptName}_Merged.cs ===`n"
$finalLines += $usingLines
$finalLines += "`n// === 本文 ===`n"
$finalLines += $bodyLines
$finalLines -replace "`n", "`r`n" | Set-Content -Path $mergedPath -Encoding UTF8
& $csc /nologo /out:$exePath $mergedPath
if (Test-Path $exePath) {
Write-Host "✅ ビルド成功:$exePath"
Add-Content -Path $logPath -Value ("✅ ビルド成功:" + $exePath)
} else {
throw "EXEファイルが生成されませんでした。"
}
}
catch {
Write-Host "❌ ビルド失敗:" + $_.Exception.Message
Add-Content -Path $logPath -Value ("❌ ビルド失敗:" + $_.Exception.Message)
}
📜 ソースコード(バッチ:MyApp.bat)
@echo off setlocal REM PowerShellスクリプトのパスを構築 set "PS_SCRIPT=%~dp0%~n0.ps1" REM PowerShellを呼び出す(エラー抑制+UTF-8対応) powershell.exe -NoProfile -ExecutionPolicy Bypass -File "%PS_SCRIPT%" endlocal pause exit
Windowsバッチの命名規則と動作仕様
- バッチファイルは、自身と同じフォルダ内にある、拡張子を除いた同名の PowerShell スクリプトを起動します。
- この命名規則により、複数のプロジェクトをわかりやすく管理できるようになります。
- このバッチは、
MyApp.batという名前で保存されていれば、同じフォルダのMyApp.ps1を起動します。MyPrj.batという名前で保存されていれば、同じフォルダのMyPrj.ps1を起動します。
🌱 ソースコードの特徴と思想的利点
| 特徴 | 意味 |
|---|---|
| 容易な設置 | |
| インストール不要 | Windows標準環境だけで完結。配布・教育に最適 |
| 命名規則による管理性 | 規則を守れば、自分がわかりやすい名前でプロジェクトを管理できる。複数のツールや用途に応じた整理が可能 |
| ファイルマージ | |
using の先頭統合 |
using の重複を防ぎ、C#構文の正しさを守りつつ、複数ファイルをマージ |
| ファイル名コメント | 元ファイルの痕跡を残すことで、履歴と思想を可視化 |
| ログ出力 | 成功・失敗の履歴を残すことで、思想の継続性を担保 |
| Visual Studioとの共存 | |
| 改行コードの統一 | Visual Studioとの共存を可能にする(CRLF) |
| 編集はVS、配布はPS | UI設計やコード補完はVS、配布用EXEはPSで生成 |
| 同期可能 | ビルド後イベントでこのスクリプトを呼び出せば、VSとPowerShellが連携 |