コンピュータや音楽の事書いてます

int[]配列をforeach-objectしたら結果が複数ならObject[] 、結果が1つだとint32

int[] にキャスト

PS> $arr = ([int[]](1..3))
PS> $arr.GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32[]                                  System.Array

foreach-objectするとObject[]

PS> $arr2 = $arr | %{ $_ }
PS> $arr2.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

結果が1つだとint32

PS> $i = $arr | %{ if($_ -eq 2) { $_ } }
PS> $i.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType

Object[] をint[] にキャスト

PS m0014525> $arr3 = ([int[]]$arr2)
PS m0014525> $arr3.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32[]                                  System.Array

1つだけ文字列にして意地悪すると、失敗のエラー

PS m0014525> $arr2[2]="abc"
PS m0014525> ([int[]]$arr2)
値 "abc" を型 "System.Int32" に変換できません。エラー: "入力文字列の形式が正しくありません。"
発生場所 行:1 文字:1
+ ([int[]]$arr2)
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) []、RuntimeException
    + FullyQualifiedErrorId : InvalidCastFromStringToInteger

現在ブラウザでログイン中のwebサイトのスクレイピング

クッキーのみでセッションが特定出来る場合 例:Redmine
EdgeやChromeの開発者ツールの「アプリケーション」タブからクッキーの名前と値をコピーして、

$url="https://xxxx.cloud.redmine.jp/issues/71643" #表示中のURL
$session = New-Object Microsoft.PowerShell.Commands.WebRequestSession
$cookie = New-Object -TypeName System.Net.Cookie
$cookie.Name = "_redmine_session" #ブラウザからもってきたcookie名前
$cookie.Value = "xxxxxx" #ブラウザからもってきたcookie値
$session.Cookies.Add($url, $cookie)
$res = Invoke-WebRequest $url -WebSession $session
$dom = $res.ParsedHtml

$domにはDOM構造が丸々入っているので、 Aタグの情報が欲しいのなら

$dom.getElementsByTagName("a") | Export-Csv a.csv -Encoding UTF8

キャッシュ類とテンポラリファイルの一括削除

Windows起動時に自動実行してしばらく使っている。
数GBくらい違う。
いまのところ不具合なし。

cd $PSScriptRoot
#準備
$tdir = (
	"$env:APPDATA\Microsoft\Teams\Cache",
	"$env:APPDATA\Microsoft\Teams\Code Cache",
	"$env:temp\",
	"$env:LOCALAPPDATA\Temp",
	"$env:LOCALAPPDATA\Microsoft\vscode-cpptools\ipch",
	"$env:LOCALAPPDATA\Microsoft\Office\16.0\OfficeFileCache",
	"$env:LOCALAPPDATA\Microsoft\Edge\User Data\Default\Service Worker\CacheStorage"
)
#更新日が今日より前
$tfiles = $tdir | dir -File -Recurse | Where-Object { $_.LastWriteTime -lt [DateTime]::Today }
#確認
#$tfiles > check.txt ; start .\check.txt
#pause
#実行
$tfiles | Remove-Item
dotnet nuget locals all -l
dotnet nuget locals all -c

WScript.Shell CreateShortcut 「値が有効な範囲にありません。」HRESULT: 0x80070057

デスクトップに bbb.ps1 ファイルを実行するショートカットaaa.lnkを作るのに

$wsh = New-Object -ComObject WScript.Shell
$lnk=$wsh.CreateShortcut("$env:USERPROFILE\Desktop\aaa.lnk")
$lnk.TargetPath="powershell -ExecutionPolicy Bypass -command ""bbb.ps1"""
$lnk.Save()

としたら「値が有効な範囲にありません。」エラーとなった。

$wsh = New-Object -ComObject WScript.Shell
$lnk=$wsh.CreateShortcut("$env:USERPROFILE\Desktop\aaa.lnk")
$lnk.TargetPath="powershell"
$lnk.Arguments="-ExecutionPolicy Bypass -command ""bbb.ps1"""
$lnk.Save()

引数部分をArgumentsにいれることで成功した。

scripting.Dictionary.keysにSortがない

ぐぐってみると .NetArrayListを使ったりという情報があるけど、そこまでしたくない時。
WorksheetFunction.Sortが使えた。

    Dim dicSum As New Dictionary, v

    'なんか格納

    For Each v In WorksheetFunction.Sort(dicSum.Keys, 1, 1, True)
        Debug.Print "key: " v & " val : " & dicSum(v)
    Next

C++Builder PostgreSQL Text[]カラムの読み込み 要素数不明の場合

TarrayField の Fields や FieldValues を使うという情報があったが、なぜか先頭要素しか取得できなかった。
FieldByName() で取得した TField を TDataSetField へキャストし、
TDataSetField の NestedDataSet->Eof を見ながら Next() していく方法でうまくいった。
XXX_array という配列カラムがある場合、

TFDConnection *con;
TFDQuery *qry;
/*---- 設定省略 ----*/
qry->open("select a, b, c, XXX_array from t_abcd;");
while (!db->qry->Eof){
    auto colArray = (TDataSetField*) qry->FieldByName("XXX_array");
    while(!colArray->NestedDataSet->Eof){
        auto str = colArray->NestedDataSet->Fields->Fields[0]->AsString;
        if(str != NULL && str.Trim() != "")
            vecXXX.push_back(str);
        colArray->NestedDataSet->Next();

Excelアドイン 比較ツール inquire を直接起動する

support.microsoft.com
便利だが、立ち上げ方法が分かりにくい。

スタートメニューから起動出来るように
%AppData%\Microsoft\Windows\Start Menu\Programs
を開き、
新規作成 → ショートカット で下記を入力し、エンター
powershell.exe -Command & """"C:\Program Files (x86)\Microsoft Office\root\Client\AppVLP.exe"""" """"C:\Program Files (x86)\Microsoft Office\Root\Office16\DCF\SPREADSHEETCOMPARE.EXE""""