2026年2月8日 星期日

如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式

系列文章:
1.如何用 ADK 製作 Windows PE 開機磁碟
2.如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式



































資料來源:
1.如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式

如何用 ADK 製作 Windows PE 開機磁碟



如何使用 Microsoft Assessment and Deployment Kit (ADK) 製作 Windows PE (Windows 預先安裝環境) 開機媒體。
1.下載及安裝 Windows ADK:
        
取得
adksetup.exe 與 adkwinpesetup.exe

2.執行 adksetup.exe 

3.執行 adkwinpesetup.exe
4.在C:\ 建立資料夾WinPE,用來存放WinPE_x64.iso
mkdir C:\WinPE
copype amd64 C:\WinPE\WinPEx64
makewinpemedia /iso C:\WinPE\WinPEx64 C:\WinPE\WinPEx64.iso



資料來源:

只要點兩下,升級電腦後完成所有驅動程式的安裝

        最近電腦需要升級,需要將原先Windows 10 升級到Windows 11。過去,總是要依據原先主機的型號,到原廠官方網站。將驅動程式一個個下載好。等到windows升級完成,再將驅動程式一個個裝好。總覺得很累人,是否有方式能夠讓我只要點兩下,升級電腦後完成所有驅動程式的安裝

下載檔案解壓密碼:demo1234
使用步驟教學:


單機測試步驟:
1.下載檔案,解壓縮。解壓密碼:demo1234
2.匯出驅動設定檔->點選ExportDriverConf.bat
3.將桌面整個InstallDriver資料夾搬到隨身碟
4.升級Windows 11
5.將隨身碟內InstallDriver資料夾搬到桌面
6.匯入驅動設定檔->點選ImportDriverConf.bat

程式目的:匯出所有驅動設定檔inf 到所在的資料夾內的config
程式名稱:ExportDriverConf.bat
程式內容:
@echo off
REM ---------------以下是程式碼,不需更改---------------
REM :: BatchGotAdmin (Run as Admin code starts)
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
REM :: BatchGotAdmin (Run as Admin code ends)
REM :: Your codes should start from the following line
echo ===============================
echo 正在匯出驅動程式(Dism)
echo 匯到:%~dp0config
echo ===============================
dism /online /export-driver /destination:%~dp0config\
echo 驅動匯出完成
pause
exit

程式目的:匯入config資料夾內所有驅動設定檔inf
程式名稱:ImportDriverConf.bat
程式內容:
@echo off
REM ---------------以下是程式碼,不需更改---------------
REM :: BatchGotAdmin (Run as Admin code starts)
REM --> Check for permissions
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
REM --> If error flag set, we do not have admin.
if '%errorlevel%' NEQ '0' (
echo Requesting administrative privileges...
goto UACPrompt
) else ( goto gotAdmin )
:UACPrompt
echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
"%temp%\getadmin.vbs"
exit /B
:gotAdmin
if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" )
pushd "%CD%"
CD /D "%~dp0"
REM :: BatchGotAdmin (Run as Admin code ends)
REM :: Your codes should start from the following line
echo ===============================
echo 正在匯入驅動程式(PnPUtil)
echo 來源:%~dp0config
echo ===============================
pnputil /add-driver "%~dp0config\*.inf" /subdirs /install
echo 驅動匯入完成
echo 請重新開機
pause
exit

資料來源:
1.如何在 Windows 系統中將驅動程式匯入和匯出到另一台電腦









2026年2月1日 星期日

只要點兩下,就能夠將所有照片分成橫式(landscape)、直式(portrait)與正方形(square) 並依照設定調整尺寸

系列文章:
1.只要點兩下,就能夠將所有照片分成橫式(landscape)、直式(portrait)與正方形(square) 並依照設定調整尺寸1.https://skjhcreator.blogspot.com/2026/02/landscapeportraitsquare.html

        經常要處理大量照片,所以希望有個程式能夠方便批次修改照片尺寸。首先該程式能夠依據設定,調整尺寸。然後分類照片,分成橫式照片、直式照片與正方形照片。
        所以,只要將未整理的照片通通放進input 資料夾內,修改設定。接下來,我只要點兩下程式,程式就會幫我調整照片尺寸,再分類照片。

       下載檔案。解壓密碼:demo1234
使用步驟:

一、安裝套件 pillow
    指令:pip install pillow

二、判別程式

from PIL import Image

def check_image_orientation(image_path):
    with Image.open(image_path) as img:
        width, height = img.size

        if width > height:
            return "橫照片(Landscape)"
        elif width < height:
            return "直照片(Portrait)"
        else:
            return "正方形照片(Square)"

# 範例使用
image_path = "test.jpg"
result = check_image_orientation(image_path)
print(result)

三、設定.txt 內容:

# 照片調整方式 1.強制拉伸 2.等比例縮放
1
# 調整尺寸 800x600
1000x800

=>設定內容說明:
    代表:強制拉伸(不等比例)
    目標尺寸:
    橫式 → 1000 x 800
    直式 → 800 x 1000
    正方形 → 1000 x 1000

四、pyPicTo800x600.py 內容:

import os
from PIL import Image

current_directory = os.getcwd()
current_directory_input = current_directory + "\\input\\"
current_directory_input_files = os.listdir(current_directory_input)

# 讀取設定.txt
with open(current_directory + "\\設定.txt", "r", encoding="utf-8") as f:
    lines = f.readlines()

# 設定 1.變形調整 2.等比例縮放
option = int(lines[1].strip())

# 尺寸 800x600
setWidth, setHeight = map(int, lines[3].strip().split('x'))

# 建立輸出資料夾
Output_landscape_path = current_directory + "\\Output_橫式\\"
Output_portrait_path  = current_directory + "\\Output_直式\\"
Output_square_path    = current_directory + "\\Output_正方形\\"

os.makedirs(Output_landscape_path, exist_ok=True)
os.makedirs(Output_portrait_path, exist_ok=True)
os.makedirs(Output_square_path, exist_ok=True)

for i in current_directory_input_files:
    with Image.open(current_directory_input + i) as img:
        width, height = img.size
        # 橫式
        if width > height:
            if option == 1:
                img = img.resize((setWidth, setHeight),Image.LANCZOS)
            elif option == 2:
                img.thumbnail((setWidth, setHeight))
            img.save(Output_landscape_path + i)
        # 直式
        elif width < height:
            if option == 1:
                img = img.resize((setHeight, setWidth),Image.LANCZOS)
            elif option == 2:
                img.thumbnail((setHeight, setWidth))
            img.save(Output_portrait_path + i)
        # 正方形
        else:
            maxvalue = max(setWidth, setHeight)
            if option == 1:
                img = img.resize((maxvalue, maxvalue),Image.LANCZOS)
            elif option == 2:
                img.thumbnail((maxvalue, maxvalue))
            img.save(Output_square_path + i)


2026年1月26日 星期一

Laravel 12 CSV 匯入與雙向查詢系統

 一、系統定位
        本系統使用 Laravel 12 建立一套 CSV 匯入系統,同時兼顧 資料驗證、安全性、API 設計與效能可將學生帳號資料寫入資料庫,並支援以「年班座號」查詢帳號 或 以「帳號」反查年班座號


二、功能清單
    1.CSV 上傳 UI(Blade)
    2.資料驗證(CSV 欄位、重複資料)
    3.密碼加密(Hash)
    4.API 回傳時隱藏密碼
    5.RESTful API 設計
    6.錯誤處理(找不到資料)

三、建立 Laravel 12 專案
    指令:composer create-project laravel/laravel csv-demo
                cd csv-demo

四、建立資料表 create_student_accounts_table
    指令:php artisan make:migration create_student_accounts_table
    編輯 database/migrations/xxxx_create_student_accounts_table.php
    =>為了提升查詢效能,針對查詢欄位建立 unique index

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('student_accounts', function (Blueprint $table) {
            $table->id();
            $table->string('grade_class_seat_no')->unique()->index();
            $table->string('account')->unique()->index();
            $table->string('password');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('student_accounts');
    }
};


五、建立Model StudentAccount
    指令:php artisan make:model StudentAccount
    編輯 app/Models/StudentAccount.php
   
=>API 回傳時自動隱藏密碼,避免敏感資料外洩
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class StudentAccount extends Model
{
    //
    protected $fillable = [
        'grade_class_seat_no',
        'account',
        'password',
    ];

    protected $hidden = [
        'password',
    ];
}


六、建立Controller StudentAccountController
    指令:php artisan make:controller StudentAccountController
    編輯 app/Http/Controllers/StudentAccountController.php
    => 使用 Hash::make 保護密碼
          使用 firstOrFail 統一錯誤處理
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use App\Models\StudentAccount;

class StudentAccountController extends Controller
{
    /**
     * CSV 匯入(Web + API 共用)
     */
    public function import(Request $request)
    {
        $request->validate([
            'csv' => 'required|file|mimes:csv,txt',
        ]);

        $file = $request->file('csv');
        $handle = fopen($file->getRealPath(), 'r');

        $header = fgetcsv($handle);

        if ($header !== ['GradeClassSeatNo', 'Account', 'Password']) {
            return back()->withErrors(['CSV 欄位格式錯誤']);
        }

        $count = 0;

        while (($row = fgetcsv($handle)) !== false) {
            $data = array_combine($header, $row);

            StudentAccount::updateOrCreate(
                ['grade_class_seat_no' => $data['GradeClassSeatNo']],
                [
                    'account' => $data['Account'],
                    'password' => Hash::make($data['Password']),
                ]
            );

            $count++;
        }

        fclose($handle);

        /**
         * 判斷來源:Web or API
         */
        if ($request->is('api/*')) {
            return response()->json([
                'message' => 'CSV 匯入完成',
                'count'   => $count,
            ]);
        }

        return redirect('/import-page')
            ->with('success', "匯入成功,共 {$count} 筆資料");
    }

    /**
     * 用年班座號查(API)
     */
    public function findBySeat($seatNo)
    {
        return StudentAccount::where('grade_class_seat_no', $seatNo)
            ->firstOrFail();
    }

    /**
     * 用帳號查(API)
     */
    public function findByAccount($account)
    {
        return StudentAccount::where('account', $account)
            ->firstOrFail();
    }

    /**
     * Blade 查詢頁
     */
    public function search(Request $request)
    {
        $request->validate([
            'seat_no' => 'nullable|string',
            'account' => 'nullable|string',
        ]);

        $student = null;

        if ($request->filled('seat_no')) {
            $student = StudentAccount::where(
                'grade_class_seat_no',
                $request->seat_no
            )->first();
        }

        if ($request->filled('account')) {
            $student = StudentAccount::where(
                'account',
                $request->account
            )->first();
        }

        return view('search', compact('student'));
    }
}


七、建立路由 與 Api 路由
    同一個匯入邏輯同時支援 Web 與 API,但依照請求來源回傳不同格式,兼顧 UX 與 API 設計。
    編輯 routes/web.php
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\StudentAccountController;

Route::get('/', function () {
    return view('index');
});

// CSV 匯入頁
Route::get('/import-page', function () {
    return view('import');
});
Route::post('/import', [StudentAccountController::class, 'import'])
    ->name('students.import');

// 查詢頁
Route::get('/search', function () {
    return view('search');
});

Route::post('/search', [StudentAccountController::class, 'search']);


    編輯 routes/api.php
<?php

use Illuminate\Support\Facades\Route;
use App\Http\Controllers\StudentAccountController;

Route::prefix('students')->group(function () {
    Route::post('/import', [StudentAccountController::class, 'import']);
    Route::get('/seat/{seatNo}', [StudentAccountController::class, 'findBySeat']);
    Route::get('/account/{account}', [StudentAccountController::class, 'findByAccount']);
});



八、建立Blade 上傳頁面 與 Blade 查詢頁面
    編輯 resources/views/import.blade.php
<!DOCTYPE html>
<html>
<head>
    <title>CSV 匯入</title>
</head>
<body>
<h2>學生帳號 CSV 匯入</h2>

<form action="{{ route('students.import') }}" method="POST" enctype="multipart/form-data">
    @csrf
    <input type="file" name="csv" required>
    <button type="submit">匯入</button>
</form>

@if ($errors->any())
    <p style="color:red">{{ $errors->first() }}</p>
@endif
@if (session('success'))
    <p style="color:green">{{ session('success') }}</p>
@endif
</body>
</html>


    編輯 resources/views/search.blade.php
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>學生帳號查詢系統</title>
    <style>
        body {
            font-family: Arial;
            margin: 40px;
        }
        input {
            padding: 6px;
            width: 250px;
        }
        button {
            padding: 6px 12px;
        }
        .box {
            margin-bottom: 20px;
        }
        .result {
            margin-top: 20px;
            padding: 15px;
            border: 1px solid #ccc;
        }
        .error {
            color: red;
        }
    </style>
</head>
<body>

<h2>學生帳號查詢(Demo)</h2>

<form method="POST" action="/search">
    @csrf

    <div class="box">
        <label>GradeClassSeatNo:</label><br>
        <input type="text" name="seat_no" placeholder="例如:30101">
    </div>

    <div class="box">
        <label>Account:</label><br>
        <input type="text" name="account" placeholder="例如:student01">
    </div>

    <button type="submit">查詢</button>
</form>

{{-- 查詢結果 --}}
@if(isset($student) && $student)
    <div class="result">
        <h4>查詢結果</h4>
        <p><strong>GradeClassSeatNo:</strong> {{ $student->grade_class_seat_no }}</p>
        <p><strong>Account:</strong> {{ $student->account }}</p>
    </div>
@endif

{{-- 查無資料 --}}
@if(isset($student) && !$student)
    <p class="error">查無資料</p>
@endif
{{-- 顯示錯誤訊息 --}}
@if ($errors->any())
    <ul class="error">
        @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
        @endforeach
    </ul>
@endif

</body>
</html>


    編輯 resources/views/index.blade.php
<!DOCTYPE html>
<html lang="zh-TW">
<head>
    <meta charset="UTF-8">
    <title>首頁</title>
</head>
<body>
    <h1>學生帳號管理系統</h1>

    <ul>
        <li>
            <a href="{{ url('/import-page') }}">CSV 匯入學生資料</a>
        </li>
        <li>
            <a href="{{ url('/search') }}">查詢學生資料</a>
        </li>
    </ul>
</body>
</html>






























如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式

系列文章: 1. 如何用 ADK 製作 Windows PE 開機磁碟 2. 如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式 資料來源: 1. 如何客製 WinPE 映像 - 新增驅動程式、更換背景圖、新增應用程式