2020年7月20日月曜日

WSUSの管理

 Windows Update から最新のセキュリティパッチを当てたいけど、サーバからのインターネット・アクセスは遮断したいよね?とか、会社の全パソコンから Microsoft Update にパッチ取りに行くのはナンセンスだよね?とか思うと、WSUS を運用する事になります。

ところが、このメジャーなWSUSの管理に関しては、ほとんど情報が無い。何故なのか?わかりません。理解に苦しみます。
しかも、このWSUS。メンテナンスを怠るとクソ重たくなって動かなくなる始末。何回、再インストールをした事か?
ほんと、素晴らしいツールである事に間違いは無いのですが、メンテナンスがしんどくて、こいつのお守りにリソースを食われます。

ここで紹介するツールは、Microsoft のブログで紹介された WSUS管理のためのScriptで、拾い物です。
ネットで検索しても見つからないので、ここに紹介します(著作権がわからないので、掲載を取りやめるかもしれません)

トップバッターは、古い更新を拒否して、新しい更新を許可するスクリプトです。残念ながら Windows Defender 関連のアップデートが対象外となってます。どなたか、わかりましたら教えてください
# ===============================================
# Script to decline superseeded updates in WSUS.
# ===============================================
# It's recommended to run the script with the -SkipDecline switch to see how many superseded updates are in WSUS and to TAKE A BACKUP OF THE SUSDB before declining the updates.
# Parameters:

# $UpdateServer             = Specify WSUS Server Name
#$UpdateServer = "wsus.your.domain";
# $UseSSL                   = Specify whether WSUS Server is configured to use SSL
# $Port                     = Specify WSUS Server Port
#$Port = 8530;
# $SkipDecline              = Specify this to do a test run and get a summary of how many superseded updates we have
# $DeclineLastLevelOnly     = Specify whether to decline all superseded updates or only last level superseded updates

# Supersedence chain could have multiple updates. 
# For example, Update1 supersedes Update2. Update2 supersedes Update3. In this scenario, the Last Level in the supersedence chain is Update3. 
# To decline only the last level updates in the supersedence chain, specify the DeclineLastLevelOnly switch

# Usage:
# =======

# To do a test run against WSUS Server without SSL
# Decline-SupersededUpdates.ps1 -UpdateServer SERVERNAME -Port 8530 -SkipDecline

# To do a test run against WSUS Server using SSL
# Decline-SupersededUpdates.ps1 -UpdateServer SERVERNAME -UseSSL -Port 8531 -SkipDecline

# To decline all superseded updates on the WSUS Server using SSL
# Decline-SupersededUpdates.ps1 -UpdateServer SERVERNAME -UseSSL -Port 8531

# To decline only Last Level superseded updates on the WSUS Server using SSL
# Decline-SupersededUpdates.ps1 -UpdateServer SERVERNAME -UseSSL -Port 8531 -DeclineLastLevelOnly

[CmdletBinding()]
Param(
 [Parameter(Mandatory=$True,Position=1)]
    [string] $UpdateServer,
 
 [Parameter(Mandatory=$False)]
    [switch] $UseSSL,
 
 [Parameter(Mandatory=$True, Position=2)]
    $Port,
    [switch] $SkipDecline,
    [switch] $DeclineLastLevelOnly
)

Write-Host ""

if ($SkipDecline -and $DeclineLastLevelOnly) {
    Write-Host "Using SkipDecline and DeclineLastLevelOnly switches together is not allowed."
 Write-Host ""
    return
}

$outPath = Split-Path $script:MyInvocation.MyCommand.Path
$outSupersededList = Join-Path $outPath "SupersededUpdates.csv"
$outSupersededListBackup = Join-Path $outPath "SupersededUpdatesBackup.csv"
"UpdateID, RevisionNumber, Title, KBArticle, SecurityBulletin, LastLevel" | Out-File $outSupersededList

try {
    
    if ($UseSSL) {
        Write-Host "Connecting to WSUS server $UpdateServer on Port $Port using SSL... " -NoNewLine
    } Else {
        Write-Host "Connecting to WSUS server $UpdateServer on Port $Port... " -NoNewLine
    }
    
    [reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null
    #$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($UpdateServer, $UseSSL, $Port);
 $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer();
}
catch [System.Exception] 
{
    Write-Host "Failed to connect."
    Write-Host "Error:" $_.Exception.Message
    Write-Host "Please make sure that WSUS Admin Console is installed on this machine"
 Write-Host ""
    $wsus = $null
}

if ($wsus -eq $null) { return } 

Write-Host "Connected."

$countAllUpdates = 0
$countSupersededAll = 0
$countSupersededLastLevel = 0
$countDeclined = 0

Write-Host "Getting a list of all updates... " -NoNewLine

try {
 $allUpdates = $wsus.GetUpdates()
}

catch [System.Exception]
{
 Write-Host "Failed to get updates."
 Write-Host "Error:" $_.Exception.Message
    Write-Host "If this operation timed out, please decline the superseded updates from the WSUS Console manually."
 Write-Host ""
 return
}

Write-Host "Done"

Write-Host "Parsing the list of updates... " -NoNewLine
foreach($update in $allUpdates) {
    
    $countAllUpdates++
    
    if ($update.IsDeclined) {
        $countDeclined++
    }
    
    if (!$update.IsDeclined -and $update.IsSuperseded) {
        $countSupersededAll++
        
        if (!$update.HasSupersededUpdates) {
            $countSupersededLastLevel++
        }
        
        "$($update.Id.UpdateId.Guid), $($update.Id.RevisionNumber), $($update.Title), $($update.KnowledgeBaseArticles), $($update.SecurityBulletins), $($update.HasSupersededUpdates)" | Out-File $outSupersededList -Append       
        
    }
}

Write-Host "Done."
Write-Host "List of superseded updates: $outSupersededList"

Write-Host ""
Write-Host "Summary:"
Write-Host "========"

Write-Host "All Updates =" $countAllUpdates
Write-Host "Any except Declined =" ($countAllUpdates - $countDeclined)
Write-Host "All Superseded Updates =" $countSupersededAll
Write-Host "    Superseded Updates (Intermediate) =" ($countSupersededAll - $countSupersededLastLevel)
Write-Host "    Superseded Updates (Last Level) =" $countSupersededLastLevel
Write-Host ""

if (!$SkipDecline) {
    
    Write-Host "SkipDecline flag is set to $SkipDecline. Continuing with declining updates"
    $updatesDeclined = 0
    
    if ($DeclineLastLevelOnly) {
        Write-Host "  DeclineLastLevel is set to True. Only declining last level superseded updates." 
        
        foreach ($update in $allUpdates) {
            
            if (!$update.IsDeclined -and $update.IsSuperseded -and !$update.HasSupersededUpdates) {
                
                try 
                {
                    $update.Decline()
                    # Write-Host "Declined update $($update.Id.UpdateId.Guid)"
                    Write-Progress -Activity "Declining Updates" -Status "Declining update $($update.Id.UpdateId.Guid)" -PercentComplete (($updatesDeclined/$countSupersededLastLevel) * 100)
                    $updatesDeclined++
                }
                catch [System.Exception]
                {
                    Write-Host "Failed to decline update $($update.Id.UpdateId.Guid). Error:" $_.Exception.Message
                }            
            }
        }        
    }
    else {
        Write-Host "  DeclineLastLevel is set to False. Declining all superseded updates."
        
        foreach ($update in $allUpdates) {
            
            if (!$update.IsDeclined -and $update.IsSuperseded) {
                
                try 
                {
                    $update.Decline()
                    # Write-Host "Declined update $($update.Id.UpdateId.Guid)"
                    Write-Progress -Activity "Declining Updates" -Status "Declining update $($update.Id.UpdateId.Guid)" -PercentComplete (($updatesDeclined/$countSupersededAll) * 100)
                    $updatesDeclined++
                }
                catch [System.Exception]
                {
                    Write-Host "Failed to decline update $($update.Id.UpdateId.Guid). Error:" $_.Exception.Message
                }            
            }
        }   
        
    }
    
    Write-Host "  Declined $updatesDeclined updates."
    if ($updatesDeclined -ne 0) {
        Copy-Item -Path $outSupersededList -Destination $outSupersededListBackup -Force
  Write-Host "  Backed up list of superseded updates to $outSupersededListBackup"
    }
    
}
else {
    Write-Host "SkipDecline flag is set to $SkipDecline. Skipped declining updates"
}

Write-Host ""
Write-Host "Done"
Write-Host ""

2番手は、クリーンアップのスクリプト2種です。中身理解してません。
きれいにして
[System.Reflection.Assembly]::LoadWithPartialName('microsoft.updateservices.administration')

$wsus=new-object 'Microsoft.UpdateServices.Administration.AdminProxy'
$wsusrv=$wsus.GetUpdateServerInstance()

$cm=$Wsusrv.GetCleanupManager()
$cs=new-object 'Microsoft.UpdateServices.Administration.CleanupScope'

$cs.CleanupObsoleteUpdates = $True

$cm.PerformCleanup($cs)
圧縮するという感じでしょうか?
[System.Reflection.Assembly]::LoadWithPartialName('microsoft.updateservices.administration')

$wsus=new-object 'Microsoft.UpdateServices.Administration.AdminProxy'
$wsusrv=$wsus.GetUpdateServerInstance()

$cm=$Wsusrv.GetCleanupManager()
$cs=new-object 'Microsoft.UpdateServices.Administration.CleanupScope'

$cs.CompressUpdates = $True

$cm.PerformCleanup($cs)

おまけで、PowerShell の実行ポリシーを変更するスクリプトです。石橋を叩いて割るセキュリティには、うんざりです。このスクリプトも効果があるのか無いのか、よくわかりません。これもどっかからの拾い物だったかと…
@ECHO OFF

REM ==============================================================
ECHO Now Checking Windows x64/x86 version information......
ECHO .
ECHO ..
ECHO ...
ECHO ....
ECHO .....
ECHO.
IF EXIST %SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe GOTO x64
GOTO x86

REM ==============================================================

:x64
REM ==============================================================

ECHO ** Your System was detected as x64bit Windows **
ECHO.
ECHO ----------------------------------------
Echo x86版 PowerShell の LocalMachine 実行ポリシー変更
ECHO ----------------------------------------

ECHO ** Currenct ExecutionPolisy **
%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe -Command "Get-ExecutionPolicy -list"

ECHO.
ECHO  ** Changing ExecutionPolisy **
%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Confirm"

ECHO.
ECHO  ** Changed After ExecutionPolisy **
%SystemRoot%\syswow64\WindowsPowerShell\v1.0\powershell.exe -Command "Get-ExecutionPolicy -list"

ECHO ----------------------------------------
Echo x64版 PowerShell の LocalMachine 実行ポリシー変更
ECHO ----------------------------------------

ECHO  ** Currenct ExecutionPolisy **
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Get-ExecutionPolicy -list"

ECHO.
ECHO  ** Changing ExecutionPolisy **
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Confirm"

ECHO.
ECHO  ** Changed After ExecutionPolisy **
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Get-ExecutionPolicy -list"

GOTO EOF

REM ==============================================================

:x86
REM ==============================================================

ECHO ** Your System was detected as x86bit Windows **
ECHO.
ECHO ----------------------------------------
Echo x86版 PowerShell の LocalMachine 実行ポリシー変更
ECHO ----------------------------------------

ECHO  ** Currenct ExecutionPolisy **
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Get-ExecutionPolicy -list"

ECHO.
ECHO  ** Changing ExecutionPolisy **
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Confirm"

ECHO.
ECHO  ** Changed After ExecutionPolisy **
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -Command "Get-ExecutionPolicy -list"

GOTO EOF

REM ==============================================================

:EOF
PAUSE

最後は、SQL Server のメンテナンス用SQLです
やる必要があるのかどうかさえ、理解していません。製品内容が複雑で専門的すぎて、DBには精通している方だと思う自分にも何をしているのか理解できない代物です。データベースが重たすぎてファッキュン!って時に神頼みで実行します。
-- Microsoft SQL Server Management を開く
-- クエリーを作成、これを貼り付ける
-- データベースに「SUSDB」を選択し、クエリを実行する
-- http://www.sqlmusings.com
-- Ensure a USE  statement has been executed first.
SET NOCOUNT ON

-- adapted from "Rebuild or reorganize indexes (with configuration)" from MSDN Books Online 
-- (http://msdn.microsoft.com/en-us/library/ms188917.aspx)
 
-- =======================================================
-- || Configuration variables:
-- || - 10 is an arbitrary decision point at which to
-- || reorganize indexes.
-- || - 30 is an arbitrary decision point at which to
-- || switch from reorganizing, to rebuilding.
-- || - 0 is the default fill factor. Set this to a
-- || a value from 1 to 99, if needed.
-- =======================================================
DECLARE @reorg_frag_thresh   float  SET @reorg_frag_thresh   = 10.0
DECLARE @rebuild_frag_thresh float  SET @rebuild_frag_thresh = 30.0
DECLARE @fill_factor         tinyint SET @fill_factor         = 80
DECLARE @report_only         bit   SET @report_only         = 1

-- added (DS) : page_count_thresh is used to check how many pages the current table uses
DECLARE @page_count_thresh  smallint SET @page_count_thresh   = 1000
 
-- Variables required for processing.
DECLARE @objectid       int
DECLARE @indexid        int
DECLARE @partitioncount bigint
DECLARE @schemaname     nvarchar(130) 
DECLARE @objectname     nvarchar(130) 
DECLARE @indexname      nvarchar(130) 
DECLARE @partitionnum   bigint
DECLARE @partitions     bigint
DECLARE @frag           float
DECLARE @page_count     int
DECLARE @command        nvarchar(4000)
DECLARE @intentions     nvarchar(4000)
DECLARE @table_var      TABLE(
                          objectid     int,
                          indexid      int,
                          partitionnum int,
                          frag         float,
          page_count   int
                        )
 
-- Conditionally select tables and indexes from the
-- sys.dm_db_index_physical_stats function and
-- convert object and index IDs to names.
INSERT INTO
    @table_var
SELECT
    [object_id]                    AS objectid,
    [index_id]                     AS indexid,
    [partition_number]             AS partitionnum,
    [avg_fragmentation_in_percent] AS frag,
 [page_count]       AS page_count
FROM
    sys.dm_db_index_physical_stats (DB_ID(), NULL, NULL , NULL, 'LIMITED')
WHERE
    [avg_fragmentation_in_percent] > @reorg_frag_thresh 
 AND
 page_count > @page_count_thresh
 AND
    index_id > 0
 
 
-- Declare the cursor for the list of partitions to be processed.
DECLARE partitions CURSOR FOR
    SELECT * FROM @table_var
 
-- Open the cursor.
OPEN partitions
 
-- Loop through the partitions.
WHILE (1=1) BEGIN
    FETCH NEXT
        FROM partitions
        INTO @objectid, @indexid, @partitionnum, @frag, @page_count
 
    IF @@FETCH_STATUS < 0 BREAK
 
    SELECT
        @objectname = QUOTENAME(o.[name]),
        @schemaname = QUOTENAME(s.[name])
    FROM
        sys.objects AS o WITH (NOLOCK)
        JOIN sys.schemas as s WITH (NOLOCK)
        ON s.[schema_id] = o.[schema_id]
    WHERE
        o.[object_id] = @objectid
 
    SELECT
        @indexname = QUOTENAME([name])
    FROM
        sys.indexes WITH (NOLOCK)
    WHERE
        [object_id] = @objectid AND
        [index_id] = @indexid
 
    SELECT
        @partitioncount = count (*)
    FROM
        sys.partitions WITH (NOLOCK)
    WHERE
        [object_id] = @objectid AND
        [index_id] = @indexid
 
    -- Build the required statement dynamically based on options and index stats.
    SET @intentions =
        @schemaname + N'.' +
        @objectname + N'.' +
        @indexname + N':' + CHAR(13) + CHAR(10)
    SET @intentions =
        REPLACE(SPACE(LEN(@intentions)), ' ', '=') + CHAR(13) + CHAR(10) +
        @intentions
    SET @intentions = @intentions +
        N' FRAGMENTATION: ' + CAST(@frag AS nvarchar) + N'%' + CHAR(13) + CHAR(10) +
        N' PAGE COUNT: '    + CAST(@page_count AS nvarchar) + CHAR(13) + CHAR(10)
 
    IF @frag < @rebuild_frag_thresh BEGIN
        SET @intentions = @intentions +
            N' OPERATION: REORGANIZE' + CHAR(13) + CHAR(10)
        SET @command =
            N'ALTER INDEX ' + @indexname +
            N' ON ' + @schemaname + N'.' + @objectname +
            N' REORGANIZE; ' + 
            N' UPDATE STATISTICS ' + @schemaname + N'.' + @objectname + 
            N' ' + @indexname + ';'

    END
    IF @frag >= @rebuild_frag_thresh BEGIN
        SET @intentions = @intentions +
            N' OPERATION: REBUILD' + CHAR(13) + CHAR(10)
        SET @command =
            N'ALTER INDEX ' + @indexname +
            N' ON ' + @schemaname + N'.' +     @objectname +
            N' REBUILD'
    END
    IF @partitioncount > 1 BEGIN
        SET @intentions = @intentions +
            N' PARTITION: ' + CAST(@partitionnum AS nvarchar(10)) + CHAR(13) + CHAR(10)
        SET @command = @command +
            N' PARTITION=' + CAST(@partitionnum AS nvarchar(10))
    END
    IF @frag >= @rebuild_frag_thresh AND @fill_factor > 0 AND @fill_factor < 100 BEGIN
        SET @intentions = @intentions +
            N' FILL FACTOR: ' + CAST(@fill_factor AS nvarchar) + CHAR(13) + CHAR(10)
        SET @command = @command +
            N' WITH (FILLFACTOR = ' + CAST(@fill_factor AS nvarchar) + ')'
    END
 
    -- Execute determined operation, or report intentions
    IF @report_only = 0 BEGIN
        SET @intentions = @intentions + N' EXECUTING: ' + @command
        PRINT @intentions     
        EXEC (@command)
    END ELSE BEGIN
        PRINT @intentions
    END
 PRINT @command

END
 
-- Close and deallocate the cursor.
CLOSE partitions
DEALLOCATE partitions
 
GO

2020年5月3日日曜日

WSACleanup でやらかした話


システムで思わぬところでエラーになって、俺関係ないやん?
そういう事ありません?

今回は、Windows の 通信Socket の初期化と終了処理でやらかした話を書きます。
ソース中の一箇所、WSACleanup の呼び出し場所が間違っていました。

正しくないコード
#include <winsock2.h>

void simpleSend( const char* str ) {
  WSADATA wsaData;

  if( !WSAStartup(MAKEWORD(2,0), &wsaData) ) {
    // 送信処理
  }
  WSACleanup();  // 初期化に失敗したのにクリーンナップが呼び出される。
  return 0;
}

これだと、WSAStartup に失敗した時も WSACleanup が呼び出されてしまいます。
WSAStartup と WSACleanup の処理は、コールカウント方式で処理されます。従って、サードパーティ製のDLLで WSAStartup していたコードが巻き添えを食らって WSACleanup されてしまうため、Socket の close 処理時にエラーになってしまうという現象となりました。
WSAStartup が失敗するタイミングとしては、アプリケーション終了間際があります。アプリケーションの終了間際にサードパーティ製のDLLが例外を送出してしまうのですが、この原因が WSAStartup が失敗したにも関わらず、WSACleanup を呼び出していた事によります。

正しいコード
#include <winsock2.h>

void simpleSend( const char* str ) {
  WSADATA wsaData;

  if( !WSAStartup(MAKEWORD(2,0), &wsaData) ) {
    // 送信処理
    WSACleanup();
  }
  return 0;
}
このように、WSAStartup に失敗したら、WSACleanup を呼び出さないようにする事が重要です。

2020年2月2日日曜日

DQウォーク雑感

GIS系システムを扱ってる関係で、GIS系ゲームは体験しとかなあかんやろ?というノリで、ポケモンGOをやってたんですが、DQウォークやり始めたら、こっちの方が面白くて、最近はDQウォークをずーっとやってます。雪が降る前は、1日15kmぐらい歩いてました。
ガチャに数万とか注ぎ込む話は聞いていましたが、DQウォークをやるまでは、あまり馴染みのない世界でした。
自分だったら、装備1個に数万円とか払うぐらいなら、Marvic Proとか、Oculus Questとか、Kayak用品、キャンプ用品、カメラ・レンズ、スキー用品を買いますね。
オンライン・ゲームは運営費がかかります。なんでガチャを否定する気はありません。
ゲームが面白いので月3000円のゴールドパス分だけは運営費として課金するスタンスで楽しんでます。
職業柄、システムの実装とかバグとか、細かいところが見えてしまうんですね。
例えば、速さ対策で回復スポットの出現を遅らせるように調整したな?とか、「じゅんび」画面表示して戻ると回復スポットの読み込みが入るけど、運営側でこれに対応して読み込み遅らせるように調整しおった!とか、あ、この辺のパラメータ調整されたな?といったような事が見えてしまうんです。
コロプラの印象は、私も例に漏れず巷で書かれているように「セコイ」です。あと、運営の中に、ゲームの売上が上がるように考えるとか、ユーザに楽しんでもらえるように考えるとか、そんな事よりも、不公正許すまじ房がいる感じがしてます。
カプコンのストリートファイターでは、バグによりアッパー昇龍拳が生まれました。これを逆手にとってコンボシステムへと昇華させて今に至ると思うのですが、不公正許すまじ房にかかると、バグで一部のプレイヤーが利益を被るのはケシカラン!今すぐ、対処すべきだ!となって、バグ修正が施され、ゲームとしての魅力がどんどん削ぎ落とされていきます。
こころのドロップ率を上げたよ!→一部のガチ勢が車で周回してランクSのこころを大量に集めている!→ケシカラン!→直ちに修正すべきだ→こころのドロップ率を今から調整して大幅に下げます→ゲームつまらなくなっちゃったよ…
こんな感じの繰り返しです。
不公正許すまじ房の提言で、高確率こころドロップの出現頻度が上がったような気がしてます(勘ぐりすぎか?)。高確率を連続してゲットする行動を取るユーザをふるい落として、こころドロップ率を下げるためなのではないかと感じてます。
で、一番つまらないと感じてるのは、ガチャの確率ですね。ゴールドパスでゲットした「ふくびき」が全然当たらない。せっかく上級職とか出てきて、面白くなってきたんですが、こころも渋い感じになってきたし、ガチャに5万とか注ぎ込まないと、やりこみ要素がどんどん減ってきて、つまんないんですわ。私のようなライト課金ユーザを切り捨てて運営した方が儲かるんだったらそれもいいと思います。
メガモンスターに関しても、社会人がメガモンスター討伐を何個もこなせると思いますか?しかも、不公正許すまじ房のせいで、妙にメガモンスターの出現数も少ない感じがしてしょうがないんですわ。おまけに 「セコイ」体質なんで、もの凄いこころを集めないといけない設定にされて、端から無理ゲー気味なんですわ。集めたこころ見てもらったらわかると思うけど、たくさん集めないとダメなやつはランクも低いです。
だいたい、メガモンスターの討伐チケットを買ってもらう気あるの?メガモンスターの出現数が少なすぎでしょ?しかも地理的不公平感を消すために変に気を回して機会損失してる感ありあり。いや、もう全然理解できません。
ゲーム自体は、ほんと面白くて、DQウォークのおかげで歩きまくってるんです。なんかねー、不公正許すまじ房みたいなのがゲームをつまらなくしちゃってるんじゃないかという気がして、しょうがないんです。
ちょっとネガティブな感想ですけど、ゲームは、ほんと楽しいです。1ユーザの意見でした。

2019年10月20日日曜日

mac が catalina になったら、色々と終わってた

catalina になったら、動作しないアプリが山のようにあったので、整理した。
ショックだったのは、ScanSnap Manager が動かない事。
富士通のサポート情報によると S1500M は Catalina に対応しませんとの事。\(^o^)/オワタ
それと同時に Adobe Acrobat Pro も\(^o^)/オワタ

やっべー、ディスプレイのカラーマネジメントのソフト ColorMunki Photo も動かないじゃないか!!!と思ってると、ColorMunki Display | MacRumor に情報がポストされてた。

 それによると、ここのソフトをダウンロードして実行し、古い ColorMunki をアンインストールする。次に i1Studio で継続してサポートされるようになったので、こちらのソフトをインストールすべし!との事

 やってみたら、接続エラー1020 でダメだったのに、1日経ってやり直したら、測定できました。※接続エラーになる場合 i1Studioを強制終了させてから実行すると良いです。

 


2019年10月11日金曜日

geotiff の変換あれこれ忘備録

ウィンドウズのバッチでまとめて見ました。
Windows 10 がコマンドプロンプトの utf-8 に対応したため、chcp 65001 をしてコマンドを実行した方が、トラブルが少ないです。

geotiff ファイルから png ファイルに変換する(goetiff to png)

if "%1"=="" goto err
chcp 65001
GDAL_TRANSLATE -OF PNG -B 1 -B 2 -B 3 %1.tif %1.png
goto end
:err
echo param1 [basefilename]
:end


geotiff を分割する(divide geotiff)

if "%1"=="" goto err
chcp 65001
echo divide geotiff 5000x5000
mkdir %1
call gdal_retile -ps 5000 5000 -targetDir %1 %1.tif
:err
echo param1 [basefilename]
:end


png の色を変換する

if "%1"=="" goto err
chcp 65001
convert %1.png -fill "#FEFEFE" -opaque "#FFFFFF" %1_.png
convert %1_.png -fill "#010101" -opaque "#000000" %1_dst.png
:err
echo param1 [basefilename]
:end


png を分割する(divide png)

if "%1"=="" goto err
chcp 65001
echo divide png 5000x5000
convert %1.png -crop 5000x5000 +repage +adjoin %1\%1_%%02d.png
:err
echo param1 [basefilename]
:end


World Fileを出力する(export world file(*.tfw) from geotiff)

if "%1"=="" goto err
chcp 65001
for %%s in (*.tif) do listgeo -tfw %%s
:err
echo param1 [basefilename]
:end

2019年10月9日水曜日

sqlcipher 対応のWindows x64版 sqlite3.dll をビルドした忘備録

前回の忘備録から3年

x64 版の sqlcipher 対応 dll をビルドしてくださいと言われて、気分はもにょーん。

sqlcipher-4.2.0 をダウンロードしてきて、ActiveTcl の32bit版、バージョン古い方を入れて
C:\Work\sqlcipher-4.2.0> nmake -f makefile.msc SQLITE_HAS_CODEC=1 USE_CRT_DLL=1 PLATFORM=x64
ってやったら、
sqlite3.c(30924): error C2061: 構文エラー: 識別子 'CRITICAL_SECTION'
sqlite3.c(30931): error C2059: 構文エラー: '}'
sqlite3.c(30986): error C2079: 'winMutex_staticMutexes' が 未定義の struct 'sqlite3_mutex' で使用しています。
sqlite3.c(30999): fatal error C1903: 直前のエラーを修復できません。コンパイルを中止します。
となって、ビルドできない。
Makefile.msc を追っていくと、ライブラリのパスが間違ってる、リンクオプションがメタメタ、その他諸々設定が反映されず、とにかくビルドできるような状況にもっていくのが大変そうだった。

そこで、nmake して生成された sqlite3.c sqlite3.h sqlite3ext.h sqlite3session.h から DLL をビルドした方が簡単な気がして試してみた。

空のDLLプロジェクトを作成

そして、sqlite3.c sqlite3.h sqlite3ext.h sqlite3session.h をプロジェクトに追加する。
プリプロセッサの定義として
SQLITE_API=__declspec(dllexport)
SQLITE_HAS_CODEC=1
を追加すればOKだ。 vcpkg を導入済みであれば、openssl もあっけなくリンクされてくる。
x64 は、stdcall 形式がなく cdecl 形式で、以下のようにエクスポートされている。

2019年10月8日火曜日

android ndk clang に変わってから、まじめに再構築してみた備忘録

Android ndk を 20.0 にして今まで動作してたコードをコンパイルしてたんですわ。
その時に、躓いた事を記録と…。

当時は APP_STL : stlport_shared と gnustl_static の2種類で、stlport にあるけど、gnustl にない。gnustl にあるけど、stlport にない。両方欲しいのだが詰んだwとか、苦労してましてん。そしたら、c++_shared と c++_static に変更されてました。
ビルドする時に、__atomic_inc とか使ってたんですけど、時代は std::atomic に変わってました。
いざ実行しようとすると、libc++_shared.so が無いとか言って、怒られる。
こいつ、どこにあんねん!(#^ω^)と怒ってたら、ドキュメントに記載されてました。

注: libc++ はシステム ライブラリではありません。libc++_shared.so を使用する場合は、APK 内に含める必要があります。Gradle を使用してアプリをビルドしている場合、この処理は自動的に行われます。

という訳で、ndk の sources/cxx_stl/llvm-libc++/libs/ 下からファイルを引っ張ってきて、apk にバンドルするようにしたら動作するようになりました。

だいたい動くようになったんですが、libtiff の部分で SIGSEGV 起こりまくり。きっと gcc から clang に変更されたので integer 系のサイズが変わったとかなんでしょう。stdint.h とかでカッチリとサイズ指定の integer 宣言してくれていればいいのですが…。
ブログを書いててよかったのは、サイズの違いでSIGSEGVと、苦しんでたんでのを思い出せた事でしょうか。

あわよくば、ndkもメンテできる体制に戻そうと思ったんですが、もうちょいかかりそうです。