2026年1月24日土曜日

RDP で毎回認証を求められるがそれを回避して認証情報なしで自動で接続する方法

RDP で毎回認証を求められるがそれを回避して認証情報なしで自動で接続する方法

概要

ダウンロードした RDP ファイルをコピーして書き換えて実行します 前回の続きです

環境

  • Windows11

monitory_rdp_file.ps1

param(
    [Parameter(Mandatory=$false)]
    [string]$RDPServer = "your.rdp.server.or.ip",
    
    [Parameter(Mandatory=$false)]
    [string]$RDPUsername = "domain\username",
    
    [Parameter(Mandatory=$false)]
    [string]$RDPPassword = "xxxx",
    
    [Parameter(Mandatory=$false)]
    [switch]$TestMode = $false
)

# Basic file logging to help diagnose scheduled task behavior
$logDir = Join-Path $env:LOCALAPPDATA "RDPFileMonitor"
if (-not (Test-Path $logDir)) {
    New-Item -Path $logDir -ItemType Directory -Force | Out-Null
}
$logPath = Join-Path $logDir "monitor.log"

# Emit a simple startup marker
("Started: " + (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')) | Out-File -FilePath (Join-Path $logDir 'started.txt') -Append -Encoding utf8

try {
    Start-Transcript -Path $logPath -Append -ErrorAction SilentlyContinue | Out-Null
} catch {}

# Get user profile path - handle both system and user context execution
$userProfile = [Environment]::GetFolderPath("UserProfile")
if (-not (Test-Path $userProfile)) {
    $userProfile = "C:\Users\username"
}
$downloadFolder = Join-Path $userProfile "Downloads"
$targetRDPFileName = "rdgateway101_vdgate_nifcloud_net.rdp"
$processedFiles = @()

Write-Host "Starting RDP file monitoring (polling method)"
Write-Host "Executed by: $env:USERNAME from host: $env:COMPUTERNAME"
Write-Host "User Profile: $userProfile"
Write-Host "Log: $logPath"
Write-Host "Target folder: $downloadFolder"
Write-Host "Target file name: $targetRDPFileName"

if ($TestMode) {
    Write-Host "Test Mode: Running one iteration only"
} else {
    Write-Host "Checking every 2 seconds..."
}

$iterationCount = 0
$maxIterations = if ($TestMode) { 1 } else { [int]::MaxValue }

while ($iterationCount -lt $maxIterations) {
    $iterationCount++
    Write-Host "Iteration $iterationCount at $(Get-Date -Format 'HH:mm:ss')" -ForegroundColor Gray
    
    try {
        if (Test-Path $downloadFolder) {
            # Clean up processed files list - remove entries for files that no longer exist
            $processedFiles = @($processedFiles | Where-Object { Test-Path $_ })
            
            $files = Get-ChildItem -Path $downloadFolder -Filter "*.rdp" -File
            
            foreach ($file in $files) {
                if ($file.Name -eq $targetRDPFileName -and $file.FullName -notin $processedFiles) {
                    Write-Host "Target file detected: $($file.Name) at $(Get-Date -Format 'HH:mm:ss')"
                    Write-Host "Full path: $($file.FullName)"
                    
                    Start-Sleep -Seconds 2
                    
                    try {
                        Write-Host "Executing RDP file: $($file.FullName)"
                        
                        # If credentials provided, cache them and modify RDP file
                        if ($RDPUsername -and $RDPPassword) {
                            Write-Host "Caching credentials for: $RDPServer"
                            
                            # Cache credentials using cmdkey (more reliable than embedding in RDP)
                            $cmdkeyCmd = "cmdkey.exe /generic:$RDPServer /user:$RDPUsername /pass:$RDPPassword"
                            Invoke-Expression $cmdkeyCmd | Out-Null
                            Write-Host "Credentials cached successfully"
                            
                            # Read original RDP file
                            $rdpContent = Get-Content -Path $file.FullName -Encoding ASCII
                            
                            # Remove or disable credential prompting settings
                            $rdpContent = $rdpContent -replace 'prompt for credentials:i:1', 'prompt for credentials:i:0'
                            $rdpContent = $rdpContent -replace 'promptcredentialonce:i:1', 'promptcredentialonce:i:0'
                            $rdpContent = $rdpContent -replace 'enablecredsspsupport:i:1', 'enablecredsspsupport:i:0'
                            
                            # Ensure username is set in RDP file
                            if ($rdpContent -notmatch 'username:s:') {
                                $rdpContent += "`r`nusername:s:$RDPUsername"
                            } else {
                                $rdpContent = $rdpContent -replace 'username:s:.*', "username:s:$RDPUsername"
                            }
                            
                            # Create temporary RDP file
                            $tempRDPPath = [System.IO.Path]::GetTempFileName() -replace '\.tmp$', '.rdp'
                            Set-Content -Path $tempRDPPath -Value $rdpContent -Encoding ASCII
                            Write-Host "Temporary RDP file created: $tempRDPPath"
                            
                            Start-Sleep -Seconds 1
                            
                            # Execute temporary RDP file with cached credentials
                            Start-Process -FilePath $tempRDPPath
                            $processedFiles += $file.FullName
                            Write-Host "Executed successfully with cached credentials"
                            
                            # Clean up temporary file after a delay
                            Start-Sleep -Seconds 3
                            Remove-Item -Path $tempRDPPath -Force -ErrorAction SilentlyContinue
                            Write-Host "Temporary RDP file cleaned up"
                        }
                        else {
                            # Execute without credentials modification
                            Write-Host "No credentials provided, executing original RDP file"
                            Start-Process -FilePath $file.FullName
                            $processedFiles += $file.FullName
                            Write-Host "Executed successfully"
                        }
                        
                        Start-Sleep -Seconds 1
                        Remove-Item -Path $file.FullName -Force
                        Write-Host "File deleted: $($file.FullName)"
                    }
                    catch {
                        Write-Error "Error executing RDP file: $($_.Exception.Message)"
                    }
                }
            }
        }
        else {
            Write-Host "Download folder not found: $downloadFolder"
        }
    }
    catch {
        Write-Error "Error during monitoring: $($_.Exception.Message)"
    }
    
    # For test mode, exit after one iteration
    if ($TestMode) {
        Write-Host "Test mode iteration complete. Exiting."
        break
    }
    
    # Normal mode: sleep before next iteration
    Start-Sleep -Seconds 2
}

Write-Host "RDP file monitor stopped at $(Get-Date -Format 'HH:mm:ss')"
Stop-Transcript -ErrorAction SilentlyContinue

最後に

RDP ファイルは中身はテキストなのでいろいろハックできます

2026年1月23日金曜日

ダウンロードフォルダを監視し RDP ファイルを自動で開く Powershell スクリプト

ダウンロードフォルダを監視し RDP ファイルを自動で開く Powershell スクリプト

概要

今の chrome ではできないので自作する必要があります

環境

  • Windows 11

ダウンロードフォルダを監視し特定の rdp ファイルが出現したら自動で実行する Powershell

  • vim monitor_rdp_file.ps1
param()

# Basic file logging to help diagnose scheduled task behavior
$logDir = Join-Path $env:LOCALAPPDATA "RDPFileMonitor"
if (-not (Test-Path $logDir)) {
    New-Item -Path $logDir -ItemType Directory -Force | Out-Null
}
$logPath = Join-Path $logDir "monitor.log"
# Emit a simple startup marker regardless of transcript support
("Started: " + (Get-Date -Format 'yyyy-MM-dd HH:mm:ss')) | Out-File -FilePath (Join-Path $logDir 'started.txt') -Append -Encoding utf8
try {
    Start-Transcript -Path $logPath -Append -ErrorAction SilentlyContinue | Out-Null
} catch {}

$downloadFolder = [Environment]::GetFolderPath("UserProfile") + "\Downloads"
$targetRDPFileName = "your-rdp-filename.rdp"
$processedFiles = @()

Write-Host "Starting RDP file monitoring (polling method)"
Write-Host "Log: $logPath"
Write-Host "Target folder: $downloadFolder"
Write-Host "Target file name: $targetRDPFileName"
Write-Host "Checking every 2 seconds..."

while ($true) {
    try {
        if (Test-Path $downloadFolder) {
            $files = Get-ChildItem -Path $downloadFolder -Filter "*.rdp" -File
            
            foreach ($file in $files) {
                if ($file.Name -eq $targetRDPFileName -and $file.FullName -notin $processedFiles) {
                    Write-Host "Target file detected: $($file.Name) at $(Get-Date -Format 'HH:mm:ss')"
                    Write-Host "Full path: $($file.FullName)"
                    
                    Start-Sleep -Seconds 2
                    
                    try {
                        Write-Host "Executing RDP file: $($file.FullName)"
                        # Use Start-Process for reliability in scheduled tasks
                        Start-Process -FilePath $file.FullName
                        $processedFiles += $file.FullName
                        Write-Host "Executed successfully"
                        
                        Start-Sleep -Seconds 1
                        Remove-Item -Path $file.FullName -Force
                        Write-Host "File deleted: $($file.FullName)"
                    }
                    catch {
                        Write-Error "Error executing RDP file: $($_.Exception.Message)"
                    }
                }
            }
        }
    }
    catch {
        Write-Error "Error during monitoring: $($_.Exception.Message)"
    }
    
    Start-Sleep -Seconds 2
}
finally {
    try { Stop-Transcript | Out-Null } catch {}
}

上記ファイルを実行する bat ファイル

権限を付与して実行する必要があるのでラッパー用のバッチファイルを作成します

  • vim monitor_rdp_file.bat
@echo off
REM This batch file launches the RDP file monitor PowerShell script
REM It will be called by Task Scheduler at user login

REM Ensure we start in the script directory (useful for relative paths)
pushd "C:\Users\username\path\to\powershell_script\"

REM Prepare simple logs for troubleshooting
set "LOGDIR=%LOCALAPPDATA%\RDPFileMonitor"
if not exist "%LOGDIR%" mkdir "%LOGDIR%" >nul 2>&1

REM Launch the PowerShell monitor hidden with execution policy bypass and redirect output to logs
powershell.exe -NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Users\username\path\to\powershell_script\monitor_rdp_file.ps1" 1>>"%LOGDIR%\ps_out.log" 2>>"%LOGDIR%\ps_err.log"

popd
exit /b 0

バッチファイルをタスクスケジューラに登録する Powershell

タスクスケジューラで動かす場合はバッチファイルを登録します

  • vim register_scheduled_task.ps1
# Create scheduled task for RDP file monitor at user login
# This script should be run with administrator privileges

$taskName = "RDP File Monitor"
$taskPath = "\"
$scriptPath = "C:\Users\username\path\to\powershell_script\monitor_rdp_file.bat"

Write-Host "Creating scheduled task for RDP file monitor..."

# Check if task already exists
$existingTask = Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue

if ($existingTask) {
    Write-Host "Task already exists. Removing..."
    Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
}

# Create task trigger (at user login)
$trigger = New-ScheduledTaskTrigger -AtLogOn

# Create task action
$workingDir = Split-Path -Path $scriptPath -Parent
$action = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/c `"$scriptPath`"" -WorkingDirectory $workingDir

# Create task settings
$settings = New-ScheduledTaskSettingsSet -MultipleInstances IgnoreNew -StartWhenAvailable

# Register the task with highest privilege
$principal = New-ScheduledTaskPrincipal -UserId "$env:USERNAME" -RunLevel Highest -LogonType Interactive

Register-ScheduledTask -TaskName $taskName -Trigger $trigger -Action $action -Settings $settings -Principal $principal -Force

Write-Host "Task created successfully!"
Write-Host "Task name: $taskName"
Write-Host "Batch file: $scriptPath"
Write-Host "Trigger: At user login"
Write-Host ""
Write-Host "The task will now run automatically when you log in to Windows."

タスクスケジューラ登録

Start-Process powershell.exe -ArgumentList "-ExecutionPolicy Bypass -Command `"& 'C:\Users\username\path\to\powershell_script\register_scheduled_task.ps1'`"" -Verb RunAs -Wait

最後に

これでログインすると自動で起動し監視を開始します
cmdkey などと組み合わせると自動でログインまでしてくれます
ただ rdp ファイルの prompt for credentials:i:1 が 0 になっていないとダメです
(1 でも自動入力する方法はないのだろうか)

2026年1月20日火曜日

Ubuntu24.04 に MySQL8.4 をインストールする方法

Ubuntu24.04 に MySQL8.4 をインストールする方法

概要

apt でインストールできます
ついでに unattended-upgrade にも対応しておきます

環境

  • Ubuntu 24.04
  • MySQL 8.4.7

インストール方法

curl -LO https://dev.mysql.com/get/mysql-apt-config_0.8.36-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.36-1_all.deb
sudo apt -y update
sudo apt -y install mysql-server

確認項目

  • root パスワードの設定
  • 既存の設定ファイル (my.cnf など) がある場合は上書きするか

動作確認

  • dpkg -l | grep 'mysql'
ii  default-libmysqlclient-dev:amd64       1.1.0build1                             amd64        MySQL database development files (metapackage)
ii  libmysqlclient-dev                     8.4.7-1ubuntu24.04                      amd64        MySQL development headers
ii  libmysqlclient24:amd64                 8.4.7-1ubuntu24.04                      amd64        MySQL shared client libraries
ii  mysql-apt-config                       0.8.36-1                                all          Auto configuration for MySQL APT Repo.
ii  mysql-client                           8.4.7-1ubuntu24.04                      amd64        MySQL Client meta package depending on latest version
ii  mysql-common                           8.4.7-1ubuntu24.04                      amd64        Common files shared between packages
ii  mysql-community-client                 8.4.7-1ubuntu24.04                      amd64        MySQL Client
ii  mysql-community-client-core            8.4.7-1ubuntu24.04                      amd64        MySQL Client Core Binaries
ii  mysql-community-client-plugins         8.4.7-1ubuntu24.04                      amd64        MySQL Client plugin
ii  mysql-community-server                 8.4.7-1ubuntu24.04                      amd64        MySQL Server
ii  mysql-community-server-core            8.4.7-1ubuntu24.04                      amd64        MySQL Server Core Binaries
ii  mysql-server                           8.4.7-1ubuntu24.04                      amd64        MySQL Server meta package depending on latest version

unattended-upgrade

  • grep -e 'Origin:' -e 'Suite:' /var/lib/apt/lists/repo.mysql.com_apt_ubuntu_dists_noble_*
/var/lib/apt/lists/repo.mysql.com_apt_ubuntu_dists_noble_InRelease:Origin: MySQL
  • sudo vim /etc/apt/apt.conf.d/58unattended-upgrades-mysql-packages
Unattended-Upgrade::Allowed-Origins {
        "MySQL:noble";
};

最後に

8.0 は 2026/04 で EOL なのでアップグレードしましょう

参考サイト

2026年1月14日水曜日

bpftrace で実行されたコマンドの親プロセスを特定する

bpftrace で実行されたコマンドの親プロセスを特定する

概要

例えば内部で curl を実行している親プロセスを特定する場合を紹介します

環境

  • Ubuntu 24.04
  • bpftrace 0.20.2

コマンド

sudo bpftrace -e '
tracepoint:syscalls:sys_enter_execve
/str(args->filename) == "/usr/bin/curl"/
{
    printf("curl executed! pid=%d comm=%s filename=%s\n",
        pid, comm, str(args->filename));
}
'

最後に

なぞのエージェントやサービスをインストールすると意図しないコマンドなどを実行することがあるので親プロセスを特定して問題ないことを確認しましょう

2026年1月13日火曜日

Tailwind CSS 超入門

Tailwind CSS 超入門

概要

試しました
nodejs だけ必要になります

環境

  • macOS 15.7.3
  • nodejs 22.15.1
  • tailwindcss 4.1.18

インストール

  • npm init -y
  • npm install tailwindcss @tailwindcss/cli

インポート

  • vim src/input.css
@import "tailwindcss";

CSS 生成

  • npx @tailwindcss/cli -i ./src/input.css -o ./src/output.css

index.html

<!doctype html>
<html>
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link href="./src/output.css" rel="stylesheet">
</head>
<body>
  <h1 class="text-3xl font-bold underline">
    Hello world!
  </h1>
</body>
</html>

動作確認

  • open index.html

最後に

これだけで「text-3xl」「font-bold」「underline」などのすでに tailwindcss に定義されているクラスを使えるようになります

Tailwind CSS はすでに定義されているクラスを組み合わせるだけで簡単にモダンなデザインができるという CSS フレームワークになります

基本は vite のプラグインとして使うようですが vite なしでも使えます

参考サイト

2026年1月12日月曜日

BasedPyright を pyright の設定に合わせる方法

BasedPyright を pyright の設定に合わせる方法

概要

pyrightconfig.json があるとそれを優先してしまうので basedpyright 用の設定ファイルを作成してそっちに記載します

環境

  • Ubuntu 24.04
  • code-server 4.107.0
  • basedpyright 1.37.1

basedpyrightconfig.json

{
  "typeCheckingMode": "basic",
  "reportUnknownParameterType": "none",
  "reportMissingTypeArgument": "none"
}

vscode 設定

  • settings.json
{
  "basedpyright.analysis.configFilePath": "./basedpyrightconfig.json"
}

最後に

pyrightconfig.json がある場合は注意しましょう

デフォルトは recommended なのですがそれだと pyright よりも厳しいようです

2026年1月11日日曜日

code-server と copilot chat プラグインを自動更新する方法

code-server と copilot chat プラグインを自動更新する方法

概要

code-server は apt 管理ではないので手動で更新する必要があります
更新するシェルスクリプトを作成しそれを cron などで回せば自動更新できるかなと思います

環境

  • Ubuntu 24.04
  • code-server 4.107.0
  • copilot chat plugin 0.35.3

スクリプト

#!/bin/bash

echo "=== Code Server をインストール/更新中..."
curl -fsSL https://code-server.dev/install.sh | sh

echo "=== systemd デーモンを再読み込み中..."
sudo systemctl daemon-reload

echo "=== Code Server を再起動中..."
sudo systemctl restart code-server@$USER
echo "✓ Code Server の準備完了"

# https://github.com/microsoft/vscode-copilot-chat/tags から最新の安定版を自動取得
# 安定板のタグ形式は x.y.z(パッチバージョンが1-3桁、日付のような8桁以上は除外)
# 検証版(0.37.2026010802など)は自動的に除外される
# ただし code-server の最新版でも copilot chat プラグインの最新版がインストールできるわけではないので注意
echo "=== Copilot Chat最新安定版を取得中..."
VERSION=$(curl -s https://api.github.com/repos/microsoft/vscode-copilot-chat/tags \
  | grep -oP '"name":\s*"\K[^"]+' \
  | grep -E '^v?[0-9]+\.[0-9]+\.[0-9]{1,3}$' \
  | head -1 \
  | sed 's/^v//')

if [ -z "$VERSION" ]; then
  echo "❌ エラー: バージョン取得に失敗しました"
  exit 1
fi

echo "✓ 取得したバージョン: $VERSION"

echo "=== vsixファイルをダウンロード中..."
curl -o "copilot-chat-${VERSION}.vsix" --compressed "https://marketplace.visualstudio.com/_apis/public/gallery/publishers/GitHub/vsextensions/copilot-chat/${VERSION}/vspackage"

echo "=== 拡張機能をインストール中..."
code-server --install-extension "copilot-chat-${VERSION}.vsix"

echo "=== クリーンアップ中..."
rm "copilot-chat-${VERSION}.vsix"

echo "✓ インストール完了! (バージョン: $VERSION)"%   

最後に

これを cron とかで回せばとりあえず最新版は常に手に入ります