更新プログラムの画面で”このPCでの更新プログラムは組織が管理しています”と表示される場合、
gpedit.msc>コンピュータの構成>管理用テンプレート>Windowsコンポーネント>WindowsUpdate
以下のサブフォルダの設定をすべて未構成にしてあるかどうか確認。
弥生会計/SQLServer 一括バックアップツールから復元で容量不足
復元処理中、容量不足でエラー表示。
まず、
compmgmt.msc>記憶域>ディスク管理>C:>ボリュームの拡張
を実施(環境によって、通常効果はない)
次に、2回に分けて復元し、圧縮を実施した。(1度目の復元後に下記実施し、残りを復元)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
USE master; -- master データベースに接続。sys.databases ビューを参照するため。 GO -- データベース名を格納する変数を宣言 DECLARE @DBName NVARCHAR(MAX); -- カーソルを宣言して、システムデータベースを除外したすべてのデータベース名を取得 DECLARE db_cursor CURSOR FOR SELECT name FROM sys.databases WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb') -- システムデータベースを除外 -- カーソルを開く(データベースのリストを準備) OPEN db_cursor; -- 最初のデータベース名をカーソルから取得 FETCH NEXT FROM db_cursor INTO @DBName; -- カーソルで取得したすべてのデータベースに対して繰り返し処理を実行 WHILE @@FETCH_STATUS = 0 BEGIN -- 圧縮コマンドを格納する変数を宣言 DECLARE @SQL NVARCHAR(MAX); -- DBCC SHRINKDATABASE コマンドを動的SQLとして構築 -- ここでは、10% の空き領域を残して圧縮する設定(必要に応じて変更可能) SET @SQL = 'DBCC SHRINKDATABASE ("' + @DBName + '", 10);'; -- 実行されるコマンドを確認するために出力(オプション) PRINT @SQL; -- 実際の圧縮コマンドが何か確認したい場合に役立つ -- 構築した SQL コマンドを実行 EXEC sp_executesql @SQL; -- 次のデータベース名をカーソルから取得 FETCH NEXT FROM db_cursor INTO @DBName; END; -- カーソル操作が完了したら閉じる CLOSE db_cursor; -- カーソルのメモリを解放 DEALLOCATE db_cursor; GO |
もし一括でDBを削除する場合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
USE master; -- master データベースに接続 GO DECLARE @DatabaseName NVARCHAR(128); DECLARE @SQL NVARCHAR(MAX); -- カーソルを宣言して、削除対象のデータベース名を取得 DECLARE db_cursor CURSOR FOR SELECT name FROM sys.databases WHERE name NOT IN ('master', 'model', 'msdb', 'tempdb') -- システムデータベースを除外 -- カーソルを開く OPEN db_cursor; -- 最初のデータベース名を取得 FETCH NEXT FROM db_cursor INTO @DatabaseName; -- すべてのデータベースに対して繰り返し処理 WHILE @@FETCH_STATUS = 0 BEGIN -- データベースをシングルユーザーモードに設定し、接続を強制切断 SET @SQL = 'ALTER DATABASE "' + @DatabaseName + '" SET SINGLE_USER WITH ROLLBACK IMMEDIATE;'; PRINT @SQL; -- 実行されるコマンドを確認(オプション) EXEC sp_executesql @SQL; -- データベースを削除 SET @SQL = 'DROP DATABASE "' + @DatabaseName + '";'; PRINT @SQL; -- 実行されるコマンドを確認(オプション) EXEC sp_executesql @SQL; -- 次のデータベース名を取得 FETCH NEXT FROM db_cursor INTO @DatabaseName; END; -- カーソルを閉じて解放 CLOSE db_cursor; DEALLOCATE db_cursor; GO |
Google Apps Script トリガー設定テスト
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
function deleteTriggers() { writeLog("trigger削除"); let triggers = ScriptApp.getProjectTriggers(); for(let i = 0; i < triggers.length; i++){ ScriptApp.deleteTrigger(triggers[i]); } } function writeLog(x){ let ss = SpreadsheetApp.getActiveSheet(); let range = ss.getRange("B1:C100"); let values = range.getValues(); for(let r = 0; r < values.length; r++){ if (values[r][0] == ""){ range.getCell(r+1,1).setValue(x); range.getCell(r+1,2).setValue( new Date().toTimeString().slice(0, 8) ); break; } } } function main() { // クリア let ss = SpreadsheetApp.getActiveSheet(); ss.clear(); ss.getRange("A1").setValue(0); writeLog("main開始"); deleteTriggers(); ScriptApp.newTrigger('trigger').timeBased().after(1000).create(); writeLog("trigger登録"); writeLog("main終了"); } function trigger() { writeLog("trigger開始"); let startTime = new Date().getTime(); while (SpreadsheetApp.getActiveSheet().getRange("A1").getValue() <= 20) { Utilities.sleep(1000); // 1秒 SpreadsheetApp.getActiveSheet().getRange("A1").setValue( SpreadsheetApp.getActiveSheet().getRange("A1").getValue() + 1 ); writeLog(SpreadsheetApp.getActiveSheet().getRange("A1").getValue()); let elapsedTime = (new Date().getTime() - startTime) / 1000; if (elapsedTime > 5){ deleteTriggers(); ScriptApp.newTrigger('trigger').timeBased().after(1000).create(); writeLog("trigger登録"); return; } } deleteTriggers(); writeLog("trigger終了"); } |
Mattermost サーバー更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
sudo systemctl stop mattermost cd /opt/ mv mattermost 20250102_mattermost wget https://releases.mattermost.com/10.3.1/mattermost-team-10.3.1-linux-amd64.tar.gz tar -xvzf mattermost*.gz cp /opt/20250102_mattermost/config/config.json /opt/mattermost/config/config.json cp -r /opt/20250102_mattermost/data /opt/mattermost/ sudo chown -R mattermost:mattermost mattermost sudo systemctl start mattermost sudo systemctl status mattermost |
AutoHotkey 最新版
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
ProcessSetPriority "High" SetMouseDelay -1 SendMode "Input" A_MaxHotkeysPerInterval := 200 InstallKeybdHook #UseHook CoordMode "Mouse", "Window" ;-------------------------------------------------------- ; "C:\Program Files (x86)\Google\Google Japanese Input\GoogleIMEJaTool.exe" -mode=config_dialog ; Hiragana>IMEを有効化 ; Muhenkan>IMEを無効化 ; エントリーを削除 ; Henkan ; Shift Henkan ; Shift Muhenkan ;-------------------------------------------------------- >+4::Send "{Enter}" >+5::Send "{Tab}" >+7::Send "{Home}" >+8::Send "{End}" >+q::Send "{&}" >+w::Send "{'}" >+a::Send "{#}" >+s::Send "{~}" >+z::Send "{^}" >+x::Send "{$}" >+u::Send "{|}" >+i::Send "{\}" >+o::Send "{@}" >+p::Send "{`%}" >+n::Send "{(}" >+m::Send "{)}" >+h::Send "{Left}" >+j::Send "{Down}" >+k::Send "{Up}" >+l::Send "{Right}" >+Backspace::Send "{Delete}" ;-------------------------------------------------------- ~sc07B:: { If (A_PriorHotkey = A_ThisHotkey && 500 > A_TimeSincePriorHotkey) { Send "{sc070}" } } sc07B & 1::Send "{F12}" sc07B & 2::Send "{F2}" sc07B & q::Send "{Esc}" sc07B & w::Send "{LWin}" sc07B & e::Send "#{r}" ;-------------------------------------------------------- ~^c:: { If (A_PriorHotkey = A_ThisHotkey && 500 > A_TimeSincePriorHotkey) { Send "{End}+{Home}^c" } } ;-------------------------------------------------------- sc079::Ctrl ; SpreadSheet対策 sc079 & 3::Send "^{Home}" ; Ctrl+Home sc079 & 4::Send "^{End}" ; Ctrl+End sc079 & q::Send "!{Left}" ; 戻る sc079 & w::Send "!{Right}" ; 進む sc079 & e::Send "^w" ; 閉じる sc079 & r::Send "!+r" ; Alt+Shift+R / TabsToWindow sc079 & Ctrl::AltTab Ctrl & sc079::Send "#{Tab}" sc079 & a::Send "^+{Tab}" ; 前のタブ sc079 & s::Send "^{Tab}" ; 次のタブ sc079 & d::Send "^+t" ; 再び開く sc079 & f::Send "^{F5}" ; 更新 sc079 & g::Send "!+g" ; Alt+Shift+G / MergeTabs sc079 & z::Send "!+z" ; Alt+Shift+Z / CloseRightTabs mm := [] Loop MonitorGetCount() { if MonitorGetWorkArea(A_Index,&L,&T,&R,&B) { mm.Push({L:L,T:T,R:R,B:B}) } } sc079 & c:: { global mm static keyDownCount1 If (A_PriorHotkey = A_ThisHotkey && 500 > A_TimeSincePriorHotkey) { keyDownCount1 += 1 If (keyDownCount1 > MonitorGetCount() - 1) { keyDownCount1 := 0 } } Else { keyDownCount1 := 0 } x := keyDownCount1 + 1 this_id := WinGetID("A") If (WinGetMinMax(this_id) = 1) { WinRestore(this_id) } WinMove((mm[x].L),(mm[x].T),,,this_id) ; 拡大縮小対策 WinMove(,,(mm[x].R - mm[x].L),(mm[x].B - mm[x].T),this_id) } sc079 & v:: { static keyDownCount2 If (A_PriorHotkey = A_ThisHotkey && 500 > A_TimeSincePriorHotkey) { keyDownCount2 += 1 If (keyDownCount2 > 1) { keyDownCount2 := 0 } } Else { keyDownCount2 := 0 } this_id := WinGetID("A") If (keyDownCount2 = 0) { If (WinGetMinMax(this_id) = 1) { WinRestore(this_id) WinMove(,,1100,750,this_id) } WinGetPos(&x,&y,,,this_id) if (x = -SysGet(16) or x = 0) { WinMove(,,1100,750,this_id) } WinGetPos(,,&w,&h,this_id) MouseMove(w/2, 9) ; 150% } Else If (keyDownCount2 = 1) { WinGetPos(,,&w,&h,this_id) MouseMove(w-5, h-5) } } ;-------------------------------------------------------- sc079 & WheelUp::Send "{PgUp}" sc079 & WheelDown::Send "{PgDn}" +WheelUp::WheelLeft +WheelDown::WheelRight MButton:: { MouseGetPos(&mx,&my,&id) if InStr(WinGetClass(id), "Chrome") { MouseClick "R" } else { MouseClick "M" } } RButton:: { MouseGetPos(&mx,&my,&id) if InStr(WinGetClass(id), "Chrome") { MouseClick "M" } else { MouseClick "R" } } ;-------------------------------------------------------- #HotIf WinActive("ahk_exe chrome.exe") +Space:: { this_id := WinGetID("A") imestate := DllCall("user32.dll\SendMessageW", "Ptr", DllCall("imm32.dll\ImmGetDefaultIMEWnd", "Ptr", this_id), "Ptr", 0x0283, "Ptr", 0x0005, "Ptr", 0) if (imestate = 1) { Send "{sc07B}" } Send "+{Space}" } ;-------------------------------------------------------- #HotIf WinActive("ahk_exe excel.exe") sc079 & a::Send "^{PgUp}" ; 前のタブ sc079 & s::Send "^{PgDn}" ; 次のタブ sc079 & f::Send "^+{L}" ; オートフィルタ +Space:: { Send "{sc07B}" Send "+{Space}" } MButton:: { MouseClick "L" Send "{F4}" } ;-------------------------------------------------------- #HotIf WinActive("ahk_exe mpc-be64.exe") sc079 & a::Send "^{PgUp}" ; 前のタブ sc079 & s::Send "^{PgDn}" ; 次のタブ w::Send "{Numpad1 10}" e::Send "^{Numpad2 10}" r::Send "{Numpad9 10}" s::Send "^{Numpad6 10}" d::Send "^{Numpad8 10}" f::Send "^{Numpad4 10}" c::Send "{Numpad5}" v::Send "!{Numpad3}" #HotIf |
GCP Javascript 複合機で受信したFAXをMattermostに投稿(PNGを投稿+PDFへのリンク)
複合機が受信したFAXをMattermostに転送してみる実験。
複合機が送信したPDF付きメールをGmailで受信し、GASでGoogleDriveからMattermostに投稿してみたが、PDFがサムネイル表示されなかった。ファイル名が自動採番なのでサムネイル表示は必須であり、そこでPDFからPNGを生成するCloud Runを作成することにした。
Cloud Runを利用し、PDFはGoogleDriveに保存したままPNGをMattermostに投稿、PNGのリンク先にGoogleDriveのPDFを指定することにした。
●Cloud Run
・プロジェクトを作成。
※ここでは、PDF2PNGというプロジェクトを作成した
・Cloud Runというプロダクトを選択し、サービスを作成する
・請求アカウントを作成(請求アカウントがないとサービスが作成できない)
※ここでは、個人クレジットカードというアカウントを作成した
・インラインエディタで関数を作成する
・サービス名:pdf2pngとした
・リージョン:そのまま
・ランタイム:Node.js 20
・承認:未認証の呼び出しを許可
・課金:リクエストベース
・インスタンスの最小数:0
・Ingress:すべて
※Cloud Build APIを有効にする必要があるとでるのでここで有効
・エディタが開くのでindex.js、package.jsonを記入
ベースイメージ: Node.js 20 (Ubuntu 22)を選択
・関数のエントリポイントを空白のまま
※ここを空白にしないとエラーになる
・保存して再デプロイを実施
・URLが表示されるので、変換できるかcurlでテスト
curl -X POST -F “file=@./xxx.pdf” https://xxx.run.app -o output.png
index.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
const express = require("express"); const multer = require("multer"); const { pdfToPng } = require("pdf-to-png-converter"); const app = express(); const upload = multer({ storage: multer.memoryStorage() }); app.post("/convert", upload.single("file"), async (req, res) => { if (!req.file) return; const pdfBuffer = req.file.buffer; const pngPages = await pdfToPng(pdfBuffer, { viewportScale: 1.0, pages: [1], }); res.setHeader("Content-Type", "image/png"); res.send(pngPages[0].content); }); app.listen(8080, '0.0.0.0'); |
package.json
1 2 3 4 5 6 7 8 9 10 11 12 13 |
{ "name": "pdf-to-png", "version": "1.0.0", "main": "index.js", "scripts": { "start": "node index.js" }, "dependencies": { "express": "^4.18.2", "multer": "^1.4.5-lts.1", "pdf-to-png-converter": "^3.6.3" } } |
GAS(時間トリガーで実行)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
let mattermostUrl = "https://xxx"; let token = "xxx"; let channelId = "xxx"; let folderId = "xxx"; let folder = DriveApp.getFolderById(folderId); let pdf2png = "https://xxx.run.app/convert"; function Main() { let threads = GmailApp.search("is:unread label:inbox subject:Attached Image"); for (let i = 0; i < threads.length; i++) { let messages = threads[i].getMessages(); for (let j = 0; j < messages.length; j++) { let message = messages[j]; if (message.isUnread()){ let attachments = message.getAttachments(); if (attachments.length > 0){ let attachment = attachments[0]; if (attachment.getContentType() == "application/pdf") { CreatePng(attachment); } } message.markRead(); } } } } function CreatePng(attachment){ let file = folder.createFile(attachment); file.setName(attachment.getName()); let fileUrl = file.getUrl(); let formData = { file: file.getBlob() }; const options = { method: "post", payload: formData, muteHttpExceptions: true }; let response = UrlFetchApp.fetch(pdf2png, options); let responseCode = response.getResponseCode(); if (responseCode == 200){ let png = response.getBlob(); PngUploadToMattermost(png,fileUrl) } } function PngUploadToMattermost(attachment,fileUrl) { let formData = { files: attachment } let endpoint = `${mattermostUrl}/api/v4/files?channel_id=${channelId}`; let options = { method: "post", headers: { Authorization: `Bearer ${token}`, }, payload: formData, muteHttpExceptions: true, }; let res = UrlFetchApp.fetch(endpoint, options); PostToMattermost(res,fileUrl); } function PostToMattermost(res,fileUrl){ let info = JSON.parse(res.getContentText()); let fileId = info.file_infos[0].id; let endpoint = `${mattermostUrl}/api/v4/posts`; let payload = { channel_id: channelId, message: `[](${fileUrl})` } let options = { method: "post", headers: { Authorization: `Bearer ${token}`, }, payload: JSON.stringify(payload), muteHttpExceptions: true, }; UrlFetchApp.fetch(endpoint, options); } |
※追記
Markdownの画像リンクはモバイルアプリで表示されないという不具合があるようだったのでfile_idsに変更。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
function PostToMattermost(res,fileUrl){ let info = JSON.parse(res.getContentText()); let fileId = info.file_infos[0].id; let endpoint = `${mattermostUrl}/api/v4/posts`; let payload = { channel_id: channelId, file_ids: [fileId], message: "--- \n" + `[PDFを開く](${fileUrl})`, } let options = { method: "post", headers: { Authorization: `Bearer ${token}`, "Content-Type": "application/json", }, payload: JSON.stringify(payload), muteHttpExceptions: true, }; UrlFetchApp.fetch(endpoint, options); } |
SlackのIncoming Webhook(App)取得
https://api.slack.com/apps
にアクセス。
・Create an App>From scratch
App Nameを決め、workspaceを選択する。
>CreateApp
管理画面が表示される。
・Incoming Webhooks
>On
・App Home>App Display Name
Display Name (Bot Name)
Default username
を決める。(ここではBot/botとした)
>Add
・Incoming Webhooks
>Add New Webhook to Workspace
通知 が xxx Slack ワークスペースにアクセスする権限をリクエストしています
と表示される。
投稿先チャンネルを指定する。
>許可する
これでURLが取得できる。
弥生会計 メニュー文字化け
弥生会計を起動すると、以下のような状態で落ちる。
イベントビューワを見ると以下のようなエラー
障害が発生しているアプリケーション名: YKaikei24.exe、バージョン: 30.4.1.105、タイム スタンプ: 0x667d081c
障害が発生しているモジュール名: ucrtbase.dll、バージョン: 10.0.19041.3636、
設定>時刻と言語>言語>管理用の言語の設定>システムロケールの変更
ベータ:ワールドワイド言語サポートでUnicode UTF-8を使用
のチェックを外すと直った。
C# デバウンス(検索用)
1 2 3 4 5 6 |
System.Threading.Timer _timer = new System.Threading.Timer(x => { Invoke(new Action(() => { xxx(); })); }); textBox1.TextChanged += (s, e) => { _timer.Change(500, Timeout.Infinite); }; |
共有フォルダにアクセスできない
Winアップデート後、ローカルネットワークの共有フォルダにアクセスしたとき、
“組織のセキュリティポリシーによって非認証のゲストアクセスがブロック…”
というメッセージが表示される。
>gpedit.msc
コンピューターの構成
管理用テンプレート
ネットワーク
Lanman ワークステーション
安全でないゲストログオンを有効にする
→有効
>gpupdate
これだけで解決しない場合
>gpedit.msc
コンピューターの構成
Windows の設定
セキュリティの設定
ローカル ポリシー
セキュリティ オプション
Microsoft ネットワーク クライアント: 常に通信にデジタル署名を行う
→無効
>gpupdate