tag:blogger.com,1999:blog-65381173242711489322024-02-25T11:37:46.109+09:00プログラミング雑記仕事とプライベートでプログラムを書いていますが、いろいろ調べたり試したりしたことをメモしていきます。Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.comBlogger163125tag:blogger.com,1999:blog-6538117324271148932.post-34477997592238767732024-02-25T11:36:00.004+09:002024-02-25T11:36:51.980+09:00Excel VBA 備忘録ときどきExcelのVBAを書きますが、普段使わない言語だとなにかとつまづきます。<br /><div>自分自身のための備忘録ですが、きっと初心者ならだれもつまづくところだと思います。</div><div><br /></div><div><b>VariantとObject</b><br /><span> </span><b>Variant</b><br /> <span> </span>すべての変数。<br /><div> <span> </span>Integerなどの値のみを持つデータ型とオブジェクト型のどちらも代入可能。</div> <span> </span>オブジェクト型=データとプロパティー、メソッドがカプセル化されたもの。</div><div><span> </span><b>Object</b></div><div><span> </span><span> </span>オブジェクト型のみ代入可能。</div><div><b><br /></b></div><div><b>代入時にSetが必要な場合、不要な場合</b></div><div><span> </span><b>Setが必要な場合</b></div><div><span> </span><span> </span>Objectに代入する場合で、値だけでなくObjectのプロパティーの設定が行われる。</div><div> <b>Setが不要な場合</b></div><div> <span> Integerなどのデータ型に</span><span>値のみ代入する場合。</span></div><div><b><br /></b></div><div><b>コンパイルエラー:プロパティーの使い方が不正です</b></div><div> Setを付けずにObjectへ代入しようとした場合。<br /></div><div><b><br /></b></div><div><b>コンパイルエラー:型が一致しません</b></div><div><b> </b>オブジェクトにIntegerなど別の型の値を代入しようとした場合。</div><div><b><br /></b></div><div><b><span style="font-family: inherit;"><span style="background-color: white; color: #333333;">実行時エラー :</span><span style="background-color: white; color: #333333;">オブジェクトが必要です</span></span></b></div><div><span style="font-family: inherit;"><span style="background-color: white; color: #333333;"><b> </b>値がNothingのオブジェクトのプロパティーにアクセスした場合。</span></span></div><div><br /></div><div><b>Sub呼び出しでCallが必要な場合</b></div><div><span><b> </b>引数がRefの場合。</span><br /></div><div><span><span> Callがない場合は引数はByRefとみなされる。</span><br /></span></div><div><span><span><br /></span></span></div><div><span><span><br /></span></span></div><div><b><span><span><br /></span></span></b></div><div><br /></div><div><br /></div><div><br /></div><div><br /></div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-77993647097477804502023-09-07T15:36:00.008+09:002023-09-08T08:34:46.759+09:00C# メール送信プログラムの「SSPIへの呼び出しに失敗しました。内部例外を参照してください。」エラー対応<p> 数年前に作ったメール送信機能のあるプログラムを作り変えようとしたら、「SSPIへの呼び出しに失敗しました。内部例外を参照してください。」エラーが発生した。</p><p>以前作ったとき、.NETのSmtpClientがexplisit SSLのみの対応の、私が使っているjcomのサーバのimplicit SSLで発生が発生したため、そのとき見つけたAegisImplicitMailを利用していた。</p><p>今回のエラーはSmtpSocketConnection.Openメソッドの中の</p><p><span> </span>sslStream.AuthenticateAsClient(host)</p><p>で発生した。</p><p>検索してみたところ、参考になる記述を発見。</p><p><span> </span></p><p><b>PowershellでSSL証明書情報取得時にTLSエラーにハマッた件</b><span><b> </b> </span><a href="https://qiita.com/pizza_slice/items/00d00fd900bb3f0fd697">https://qiita.com/pizza_slice/items/00d00fd900bb3f0fd697</a></p><p><strong style="background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.87); font-family: YakuHanJPs, -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Hiragino Kaku Gothic ProN", Meiryo, sans-serif; font-size: 16px; margin: 0px; padding: 0px;">Windows Server 2016</strong></p><p><span color="rgba(0, 0, 0, 0.87)" face="YakuHanJPs, -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Hiragino Kaku Gothic ProN", Meiryo, sans-serif" style="background-color: white; font-size: 16px;">Window 10 21H2 だったら正常にコマンドが通る。</span><br style="background-color: white; box-sizing: inherit; color: rgba(0, 0, 0, 0.87); font-family: YakuHanJPs, -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Hiragino Kaku Gothic ProN", Meiryo, sans-serif; font-size: 16px; margin: 0px; padding: 0px;" /><span color="rgba(0, 0, 0, 0.87)" face="YakuHanJPs, -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Hiragino Kaku Gothic ProN", Meiryo, sans-serif" style="background-color: white; font-size: 16px;">恐らくこれもOS依存のTLSのバージョンの問題。</span></p><p># 下記を参考にしてオーバーロード<br /># AuthenticateAsClient(String, X509CertificateCollection, SslProtocols, Boolean)<br /># Tls12:3072<span style="white-space: pre;"> </span>TLS1.2セキュリティ プロトコルを指定します$stream.AuthenticateAsClient($commonName, $null, "3072", $false)</p><div><br /></div><div>同じ理由かもしれないと、AuthenticateAsClientをこれに対応するメソッドに置き換えてみる。</div><div><br /></div><div><span> </span>sslStream.AuthenticateAsClient(host, null, (SslProtocols)3072, false);</div><div><br /></div><div>するとエラーが発生しなくなった。</div><div>(SslProtocols)3072 としたのは、プロジェクトの.NETのバージョンのせいかと思うが、SslProtocols 列挙型に<span face=""Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif" style="background-color: white; color: #161616; font-size: 14px;">Tls12が含まれていなかったため、強引にそのInt値をcastしたからです。</span></div><div><span style="color: #161616;"><span style="background-color: white; font-size: 14px;">列挙型の名前とint値の対照は次のページを参照してください。</span></span></div><div><span face=""Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif" style="background-color: white; color: #161616; font-size: 14px;"><br /></span></div><div><span face=""Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif" style="background-color: white; color: #161616; font-size: 14px;"><b>SslProtocols 列挙型</b></span></div><div><span face=""Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif" style="background-color: white; color: #161616; font-size: 14px;"><a href="https://learn.microsoft.com/ja-jp/dotnet/api/system.security.authentication.sslprotocols?view=net-7.0">https://learn.microsoft.com/ja-jp/dotnet/api/system.security.authentication.sslprotocols?view=net-7.0</a></span></div><div><br /></div><div>追記</div><div><br /></div><div>エラーが発生したのは.NET4.0でした。4.5(以上)に変更するとSslProtocols .<span style="background-color: white; color: #161616; font-size: 14px;">Tls12が定義されており、上記のintからのcastは不要になります。</span></div><div><span style="background-color: white; color: #161616; font-size: 14px;"><br /></span></div><div><span style="background-color: white; color: #161616; font-size: 14px;">なお、このプロジェクトで使用している</span>AegisImplicitMailの.NETバージョンの関係で、4.5より新しいバージョンでは試していません。SslProtocols .Defaultの値にTls12が含まれていれば、AuthenticateAsClient(host)でもエラーが発生しなくなるでしょう。</div><div><span style="background-color: white; color: #161616; font-size: 14px;"><br /></span></div><div><span style="background-color: white; color: #161616; font-size: 14px;"><br /></span></div><div><span style="background-color: white; color: #161616; font-size: 14px;"><br /></span></div><div><span style="background-color: white; color: #161616; font-size: 14px;"><br /></span></div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-51534820491713759102023-09-04T07:11:00.007+09:002024-02-25T08:15:22.903+09:00VB Excelのシートを名前で探す方法 高速版<p>VBAでExcelのシートを名前で探す方法を調べると、たいていループで名前が一致するものを探す方法が紹介されいます。</p><p>たとえばこんなコードです。</p><p> Sub Sample1(name As String)<br /> <span> </span> For i = 1 to Worksheets.Count<br /> <span> </span>if Worksheets(i).name = name Then<br /><span> </span><span> </span> Debug.Print Worksheets.Index<br /> <span> </span>Exit For<br /> <span> </span>End If<br /><span> </span> Next<br /><span> End Sub</span><br /></p><p>一回だけ実行する場合は十分高速で問題ないでしょう。しかしループの中でさらにこのループを実行しするため、場合によってはかなり時間がかかります。 かつ結果"シート名"と一致するものがない場合はシート数Xループ回数実行され、 無駄に時間を浪費します。</p><p>上記の例ではWorksheets(i)と引数にindexを使用しています。またiの範囲がCountの範囲内なので、Worksheet(i)がエラーを起こすこともありません。</p><p>Worksheetsは引数にシート名を使用することもできます。そこで次のようなコードを試してみます。</p><p><span> </span>Dim sheet As Worksheet<br /><span> </span>Set sheet = Worksheets("シート名" )<br /></p><p>"シート名"のWorksheetが存在する場合は問題ないのですが、存在しない場合は「インデックスが有効範囲にありません。」というエラーが発生します。Worksheet(i)でもiが有効範囲外であれば同じエラーが発生しますので、内部では同様のループ処理が行われていることが想像できます。</p><p>今度は、つぎのような方法を試してみます。</p><p><span> </span>Sub Sample2(name As String)<br /> <span> </span>On Error GoTo NotFound<br /> <span> </span>Debug.Print Worksheets(name).Index<br /><span> </span>NotFound:<br /><span> </span>End Sub</p><p>これでエラーが回避でき、コードもすっきりしているかと思います。面白いことに、計測してみると単純ループの55~60%程度の処理速度となります。75~80%のスピードアッ!!とも言えます。内部的にはループと同等のことを行っていると思いますが、コンパイル済みかどうかの差が大きいのでしょう。</p><p>ループによる実行回数が数千回になるような場合は、数単位での差になるのでバカにできません。</p><p>このひとつ前のブログ『InternetExplorer.getElementById 「オブジェクトが必要です」エラー対策』で使用した「On Error Resume Next」も試してみました。</p><p><span> </span>Sub Sample3name As String)<br /> <span> </span>Dim sheet As Worksheet<br /> <span> </span>On Error Resume Next<br /> <span> </span>Set sheet = Worksheets(name)<br /> <span> </span>If Not sheet Is Nothing Then<br /> <span> </span>Debug.Print Worksheets(name).Index<br /> <span> </span>End If<br /><span> </span>End Sub</p><p>これは処理速度的にはSample2と同等でした。この例の場合ではSample2の方がコード的にもすっきりしていますが、使用する場面では使い道があるかもしれせん。</p>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-83798282354449729012023-08-18T07:16:00.006+09:002023-09-04T07:13:40.752+09:00VB InternetExplorer.getElementById 「オブジェクトが必要です」エラー対策<p>VB InternetExplorer.getElementById 「オブジェクトが必要です」エラー対策</p><p>VBの InternetExplorer.getElementById は該当する要素がない場合に「オブジェクトが必要です」が発生する。これの扱いに困ったが、次の要領で対処できた。</p><div>まずは、次のようなコードでエラーが発生する。</div><div><p> Dim elm As IHTMLElement<br /> Set elm = ie.document.getElementById("someID")</p></div><div>要素がない場合にgetElementById はNullを返す。</div><div>Nullを代入できるのはVariant型だけなので、IHTMLElementとかObjectで宣言した変数に代入しようとすると「オブジェクトが必要です」が発生する。</div><p>そこで、次のようなコードにしてみる。</p><p> Dim elm As Variant<br /> Set elm = ie.document.getElementById("someID")<br /><br />こんどは「型が一致しません」エラーが発生する。<br />これはSetではNullをObjectとして扱おうとするため発生する。</p><p>それでは、これではどうだろう。</p><p> Dim elm As Variant, divs as IHTMLElementCollection<br /> elm = ie.document.getElementById("someID")<br /> if IsNull(elm) Then Exit Sub</p><p> Set divs = ul.getElementsByTagName("div")</p><p>Nullのときの処理はうまくいくが、今度はelmがObjectとして設定されていないため、後続のコードで「オブジェクトが必要です」エラーが発生する。</p><p>そこで次のように変更し、エラー発生時に処理を継続してみた。</p><p> On Error Resume Next<br /> Set elm = ie.document.getElementById("someID")<br /> If IsNull(elm) Then Exit Sub</p><p> Set divs = someID.getElementsByTagName("div")</p><div>一応うまく処理できるようになったが、ちょっとおかしい。</div><div>IsNull(elm)がTrueにならない。この場合、elmがEmpty値になっている。</div><div>Setで代入するので、elmはObjectでなければならず、Nullにはならないということですね。</div><div>そのまま後続処理に進んでも上記のコードではエラーは発生しないが、具合が悪い場合もあるかもしれない。</div><div><br /></div><div>そこで、次のようにするとIFの判別を次のようにすると有効になる。<br /><br /></div><div> On Error Resume Next</div><div> Dim elm As Object, divs as IHTMLElementCollection<br /> elm = ie.document.getElementById("someID")<br /> If elm Is Nothing Then Exit Sub <p>On Error Resume Nextとした結果 elm がEmpty値になるため、elmをObjectで宣言している。</p><p>次の式でも判別できる。</p><p> If IsEmpty(elm) Then Exit Sub</p><div>NothingはObjectとして空の状態、EmptyはVariant型として空の状態ということですね。Set式のあとなので実際にはObjectとして扱ってよいと思いますが、Dimで宣言した型に合わせるのがコード的には一貫性があると言えるでしょう。</div><div><br /></div><div>実際にはNullになることはないが、次の方がより安全かもしれない。</div><p> If IsNullOrEmpty(elm) Then Exit Sub</p><p>なお、</p></div><p> On Error Resume Next<br /></p><p>でエラーを無視するようにしたので、前後の処理の関係ではこのあとで再度On Errorを設定しなおす必要があるでしょう。</p>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-69520573957797685792022-10-04T21:51:00.172+09:002024-02-11T21:35:32.599+09:00 DELL Inspiron 14 3452 復活奮闘記<p>DELL Inspiron 5458を使用していますが、しばらく前にキーボードの一部が反応しなくなってしまいました。交換部品を探したがお手軽なものがなく、ヤフオクやメルカリで5458の出物をしばらく待っていましたが、安いものはキーボードのテストをしていないとか、メモリもHDDも取り外されて廃墟状態になったようなものばかり。</p><p>そこで、同じ型のキーボードと思しきInspiron 3452をヤフオクで落札(これもジャンク品)。送料込で3,500円。結果的には目的のキーボードに加え、ACアダプタと8Gバイトメモリも入手できたので十分元は取れたと思ってます。</p><p>残りは部品取りに使えればよいと思って思っていました、分解、組み立てを行っているうちに具合が悪かったキーボードが何かの拍子に復活し、3452も一応使用可能な状態に組み上がりました。そうなるともったいなくなり、なんとか使える状態にしておこうと奮闘が始まりました。</p><p>奮闘というのは、3452というモデルが32G eMMCが換装不可で、HDDスペースは空いているもののコネクタがないといった、いささか特異な仕様が故です。入手したときには容量不足でWindows Updateもできない状態に陥っていました。</p><p>この貧弱な仕様のおかげでWeb閲覧やメール程度の使用しかしていなかったのか、ジャンク品とはいえキーボードもACアダプタも良好でした。部品取り目的なら3452は狙い目かもしれません。</p><p>私が入手したマシンはCPUがCeleron N3050 2コア、Windows 10 64bitで、サクサク感はイマイチながら光学ドライブ、HDD無しなため5458より軽量になってます。あれこれ試してみた結果、ちょっと持ち歩いて軽い使い方をするには悪くないと思い始めてます。</p><p>さて、インタネットで見ると皆さん工夫したり、苦労したり、諦めたりしているようです。</p><p><a href="https://pc-freedom.net/use-pc/install-linux-on-dell-inspiron-14-3452/" target="_blank">クセが強いジャンクの Dell Inspiron 14-3452 へ Linux をインストールしてみた。</a></p><p><a href="https://blog.goo.ne.jp/askitdeki/e/783be8bde0ad463737ee412765d24c95" target="_blank">Dell Inspiron 14-3452 eMMC 32GB Win10 ⇒ 1709 アップデート作法</a></p><p><a href="https://bbs.kakaku.com/bbs/K0000816038/SortID=20648613/" target="_blank">Inspiron 14 3452のメモリ増設とSDDの交換ってできませんか?</a></p><p><a href="https://www.amazon.co.jp/Dell-Inspiron-14-16Q32-Windows10/product-reviews/B016W1R63E" target="_blank">amazon カスタマーレビュー</a></p><div><div><a href="https://www.dell.com/community/Storage-Drives-Media/How-to-install-SSD-for-Inspiron-14-3452/td-p/4719538" target="_blank">How to install SSD for Inspiron 14 3452?</a></div></div><div><br /></div><div>これらを参考にいろいろ試したので、今後のために書き留めておきます。</div><div>なお、手間がかかるので追試検証など不十分です。</div><div><br /></div><div>--------------------</div><div><br /></div><div><b>番外編</b></div><div><b>DELL Inspiron 5458のキーボード故障への応急対策</b></div><div>一部のキーが無反応になったため、まずはWindows付属のスクリーンキーボードで対応。</div><div>キー入力の途中でキーボードからマウスに手を移すのが面倒なため、<b><a href="https://www.vector.co.jp/download/file/winnt/util/fh539153.html" target="_blank">KeySwap for XP</a> </b>を導入。普段使わないFuntion keyへ割り当てる。</div><div><br /></div><div><b>5458と</b><b>キーボード</b><b>互換のモデル</b></div><div><div><a href="https://ja.aliexpress.com/item/1005001450932639.html" target="_blank">Ali-Expressのキーボードの広告</a>があった。これ自体はBR(ブラジル?)キーボードのものだが、キーボード表裏の写真から互換性がありそうと判断し、3452の購入を決めた。3452と互換性があるモデル、と言い換えもできる。保証はないが互換性がある可能性大。</div><div><br /></div><div>Dell Inspiron 14-3000 3441 3442 3443 3451 <b>3452</b> 3458 3459 5447 5442 5445 5448 5451 5455 <b>5458</b> 7447 5452 5457 5459用brキーボード</div></div><div><br /></div><div><b>準備</b></div><div><b>バックアップ</b></div><div>お約束として、大幅なシステム変更を行う前はバックアップを取りましょう。システムイメージを作っておいたほうよいでしょう。</div><div><br /></div><div>--------------------</div><div><br /></div><div><b>レベル1</b></div><div>特別なことはせず、そのまま使う場合のTIPS</div><div><b><br /></b></div><div><b>ディスククリーンアップ</b></div><div>Cドライブの空き容量を少しでも増やす。</div><div>エクスプローラでCドライブを選択⇒プロパティー「ディスクのクリーンアップ(D)」</div><div>⇒「OK」実行</div><div>⇒プロパティー左下の「システム ファイルのクリーンアップ」も実行</div><div><br /></div><div>dism.exeというコマンドでクリーンアップする方法もあります。これで更新ファイルを全部削除するようです。</div><div><div>>dism /Online /Cleanup-Image /RestoreHealth </div></div><div><br /></div><div><b>Windows Updateのクリーンアップ</b></div><div>設定⇒システム⇒(左ペイン)記憶域⇒「記憶域の管理」</div><div>またはWindows Update⇒「関連するリンク」グループの「ストレージを確認する」</div><div>⇒「ストレージセンサーを構成するか、今すぐ実行する」</div><div>⇒「今すぐ空き領域を増やす」の「今すぐクリーンアップ」</div><div><br /></div><div><b>OneDriveの設定確認</b></div><div>タスクバーのOneDriveアイコンクリック</div><div>⇒設定(歯車アイコン)⇒設定(メニュー)</div><div>⇒「ファイルオンデマンデド」がチェックされていることを確認</div><div><br /></div><div><b>Windowsオフラインアップデート</b></div><div>メモリ容量不足の場合はインストールメディアを作り、オフラインアップデートを試す。</div><div><br /></div><div>Microsoftの「<a href="https://www.microsoft.com/ja-jp/software-download/windows10" target="_blank">Windows 10 のダウンロード</a>」ページ</div><div>⇒「ツールを今すぐダウンロード」をダウンロードでUSBインストールメディアを作成</div><div>最新のメジャーリリースなので、既存バージョンより新しいとは限らない。</div><div><br /></div><div>USBインストールメディア装着</div><div>⇒再起動時にF12キー連打</div><div>⇒起動オプション表示</div><div>⇒USB起動(バッテリー不良でBIOSの警告画面が出るようなら、バッテリーを外して起動)</div><div>⇒言語/キーボード選択⇒OK</div><div>⇒「今すぐインストール」</div><div>⇒「適用される通知とライセンス条項」</div><div>⇒(同意するなら)「同意します」にチェック⇒「次へ」</div><div>⇒「アップグレード:Windowsをインストールし、ファイル設定、アプリを引き継ぐ」</div><div><br /></div><div>参考:<a href="https://blog.goo.ne.jp/askitdeki/e/783be8bde0ad463737ee412765d24c95" target="_blank">Dell Inspiron 14-3452 eMMC 32GB Win10 ⇒ 1709 アップデート作法</a></div><div><br /></div><div><b>Windows再インストール</b></div><div>実は、私はWindows 10を再インストールしています。中古で入手し、容量不足でWindows Updateもできない状態ですから、そこから復旧する意味はありません。Windowsオフラインアップデートと同じ要領でインスールメディア作り、内蔵eMMCを初期化してインストールしました。</div><div><br /></div><div>インストール後、いくつかドライバが正常動作しません。Dellのサイトからダウンロード、インストールします。</div><div><div><div><a href="https://www.dell.com/ja-jp/shop/supportassistforpcs/cp/supportassistforpcs" target="_blank">PC向けSupportAssistサイト</a></div><div><a href="https://www.dell.com/support/home/ja-jp/drivers/driversdetails?driverid=t6f1w" target="_blank">Realtekメモリー カード リーダー用ドライバー</a></div></div></div><div><br /></div><div>ドライバアップデート後にWiFiのパスワード再設定が必要。</div><div><br /></div><div>Windows再インストール直後にフォルダ構成変更を行う場合は、Windows Updateを一旦停止するのがよい。作業中にもバックグランドでダウンロードやインストールが行われるため、作業に支障が出たり、フォルダ移動により不具合が出る可能性がある。</div><div><br /></div><div><b>Windowsアップデートの一時休止</b></div><div>フォルダ移動の作業中にもWindowsアップデートがバックグランドで動作し、Cドライブの容量が不足する可能性がある。作業が一段落つくまでWindowsアップデートを休止する。</div><div><br /></div><div><b>休止モードの無効化</b></div><div>休止モードが有効だとC:\hiberfil.sysに復帰のためのデータが保存されるため、Gバイト超えに肥大する。</div><div><br /></div><div>メインメモリに余裕がないためか、設定の電源オプションには休止モードの有効/無効に関する項目が表示されないが、hiberfil.sysが肥大化していた。そのため、コマンドで無効にする。管理者モードのCMD.EXEで実行する。</div><div><br /></div><div><div>>powercfg.exe /hibernate off</div></div><div><br /></div><div>hiberfil.sysは「保護されたオペレーティングシステムファイル」に属するため、デフォルトではエクスプローラで表示されない。エクスプローラのオプション⇒表示で「保護されたオペレーティングシステムファイルを表示しない(推奨)」のチェックを外す。</div><div>CMD.EXEのDIRで表示するには"/AS"のオプションを付ける。</div><div><br /></div><div>バッテリー切れになるとシステムダウンとなるので、長時間のスリープには注意が必要になる。</div><div><br /></div><div>参考:<a href="https://learn.microsoft.com/ja-jp/troubleshoot/windows-client/deployment/disable-and-re-enable-hibernation" target="_blank">Windows を実行しているコンピューター上で休止状態を無効にする方法および再度有効にする方法</a></div><div><br /></div><div><div><b>ライブラリの移動</b></div><div>「ドキュメント」「ピクチャ」「ミュージック」などのライブラリをUSBメモリに移動。</div><div>「ドキュメント」などのフォルダを右クリック</div><div>⇒プロパティ⇒場所</div><div>⇒フォルダパスを変更(ドライブ名をUSBメモリのドライブ名に変更)⇒移動</div><div>⇒「フォルダー"...."は存在しません。新たに作成しますか?」の場合は「はい(Y)」</div><div>⇒移動の確認ダイアログ「はい(Y)」</div><div><br /></div><div>参考:<a href="https://paso.123net.jp/windowstips/%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%AE%E5%A0%B4%E6%89%80%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%A6%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E7%A7%BB%E5%8B%95%E3%81%99%E3%82%8B/" target="_blank">ライブラリの場所を変更してファイルを移動する方法</a></div><div><span style="font-family: "MS 明朝", serif;"><br /></span></div><div><b>新しいコンテンツの保存先変更</b></div><div>設定⇒システム⇒ストレージ⇒新しいコンテンツの保存先を変更する</div><div><div>CドライブからDドライブへ変更</div><div><br /></div></div></div><div><div><b>OneDriveを移動</b></div><div>サブマシンとして使用する場合、OneDriveでメインマシンとデータ共有しておくと用途が広がる。</div><div><b><br /></b></div><div>OneDriveのフォルダに指定するドライブはNTFSでフォーマットされている必要がある。</div><div>USBがFATでフォーマットされている場合は次のコマンドで変換可能。</div><div>>convert D: /fs:ntfs ("D:"の部分は実際のドラブ文字で置き換え)</div><div><br /></div><div><div>タスクバーのOneDriveアイコンクリック</div><div>⇒設定(歯車アイコン)⇒設定(メニュー)</div><div>⇒ アカウントタブ⇒「このPCのリンク解除」</div></div><div>⇒サインアウト後、OneDrive設定のダイアログ表示</div><div>⇒「OneDriveを設定」ダイアログ⇒アカウント入力しサインイン</div><div>⇒「OneDreveフォルダー」ダイアログ⇒左下の「場所の変更」でUSBへ移動</div><div><br /></div><div>USBへ移動後はファイル オンデマンドをOFFにしておいた方が良いでしょう。</div><div>上の「OneDriveの設定確認」参照</div><div><br /></div><div>参考:<a href="https://support.microsoft.com/ja-jp/office/onedrive-%E3%83%95%E3%82%A9%E3%83%AB%E3%83%80%E3%83%BC%E3%81%AE%E5%A0%B4%E6%89%80%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B-f386fb81-1461-40a7-be2c-712676b2c4ae" target="_blank">OneDrive フォルダーの場所を変更する</a>(Microsoft)</div></div><div><br /></div><div><div><b>Tempの移動</b></div><div>Windows使用中にTempにデータが溜まり、容量不足の原因になります。シャットダウン後も残るデータもあります。USB3.0ならTempも移動した方がよいでしょう。USB2.0だと速度の問題が出そうです。</div><div><ul><li>Temp移動は起動直後に行う。</li><li>Cドライブのプロパティーで一時ファイルを削除する。<br /> 「ディスクのクリーンアップ」で「一時ファイル」を削除<br /> 「システム ファイルのクリーンアップ」で「一時ファイル」を削除</li><li>Tempフォルダにファイルが残っている場合は、移動先のTempフォルダにコピーする。</li><li>robocopyコマンドでコピーした方がファイル属性が保存されて安全だと思います。<br />実行例(管理者権限でcmd.exeを起動)<br />>robocopy C:\Windows\Temp D:\Windows\Temp /MIR<br />>robocopy C:\Users\<i>usrename</i>\AppData\Local\Temp D:\...\Temp /MIR</li><li>環境変数のTEMP、TMPをUSBメモリのパスに書き換える<br />参考:<a href="https://yabeshin.com/post-2254/" target="_blank">【Windows10】一時フォルダを別ドライブに移動して高速化する</a></li><li>変更直後に再起動</li></ul></div><div>再起動後、不要になったTempフォルダが空でない場合は削除する。</div><div>私は、念のため一旦フォルダをリネームし、再起動後にフォルダ内のデータを削除し、空のフォルダを残した。(環境変数に関わらずC:\Windows\Tempを使用するプロセスがあるようだ。)</div><div>Tempフォルダのリネーム、削除がアクセス権なしで失敗する場合は、cmd.exeを管理者権限で起動し、ren、rmdirなどのコマンドで操作する。</div></div><div><br /></div><div>--------------------</div><div><b>レベル2</b></div><div><b>USBメモリまたはSDカード常時装着&</b><b>固定ドライブ化</b></div><div>速度的にはUSB3.0(以上)がお勧めです。本体左側がUSB3.0、右側がUSB2.0です。</div><div>USB3.0なら内蔵eMMCと同等の速度が期待できます。</div><div>SDカードスロットはUSB2.0なので、高速なSDカードを使ってもそれなりの速度しかでません。</div><div>以下、SDカードも含めUSBメモリとします。また、ドライブ文字をDとします。</div><div><br /></div><div><div>どのような方法にせよUSBメモリにデータを保存すれば紛失時のデータ流出の危険があります。そのような心配のない用途に限るか、心配なら(私は試していませんが)BitLockerによる保護などが必要です。</div><div><br /></div><div>eMMCやUSBメモリのデータ圧縮はまだ試していません。Cドライブ全体を圧縮すると起動が遅くなると決めつけているからですが、Cドライブの残り容量があまりに少ないので検討してみる予定です。</div></div><div><br /></div><div><b>USBメモリを固定ドライブ化</b></div><div>アプリケーションをUSBメモリにインストールをしようとすると「インストール ディレクトリはローカル ハード ドライブにあることが必要です。」と警告される。</div><div><div>そこで、いくつかの方法を試した。</div></div><div>ファイル/フォルダ削除でゴミ箱移動が可能になる方法もある。</div><div><br /></div><div>USBメモリにアプリをインストールした後、アンインストール時に,msiフォルダが作成できないというダイアログが表示され、アンインストールに失敗することがある。検証不十分だが、パーティションをactiveにするとエラーが発生しなくなっている。</div><div>参考:<a href="https://learn.microsoft.com/ja-jp/windows-server-essentials/install/create-a-bootable-usb-flash-drive" target="_blank">ブート可能な USB フラッシュ ドライブの作成</a></div><div><br /></div><div><b>方法1</b></div><div>USBメモリ上のファイルをVHD(Virtual Hard Disk)に割り当てる。</div><div>HDDとして扱ってくれることで、アプリケーションのインストールやライブラリ類の移動、ファイル履歴の保存先に選択などが行える。</div><div><br /></div><div>また、リムーバルディスクの場合にファイル/フォルダ削除はゴミ箱への移動ではなく完全削除となり、かつ削除のたびに「このファイルを完全に削除しますか?」のダイアログが表示されるが、<u>この方法だとファイル/フォルダ削除がゴミ箱移動となる</u>。</div><div><br /></div><div>VHDは再起動時にマウントする必要がある。タスクスケジューラで自動マウントを設定する。</div><div><br /></div><div>参考:<a href="http://siso-lab.net/yoga-book-vhd-auto-attach/" target="_blank">仮想ディスクをWindows起動時に自動マウント(アタッチ)するシンプルな方法</a></div><div><br /></div><div>タスク設定時にユーザのパスワードを要求される。PINではダメなので、ローカルユーザに変更し、パスワードを設定しておく。</div><div><br /></div><div>欠点として、(設定の問題があるかもしれないが)サインイン前にマウントが完了していないことが多く、その場合にサインイン時の環境が不完全な状態となる。手動でマウントするか、エクスプローラの再起動や再サインインが必要が必要になる。これが許容できるなら、良い方法と思う。</div><div><br /></div><div>サインイン直後にマウントが完了していないとディスクトップ、タスクバーの再現ができないため、デスクトップはDドライブに移動した。この場合、デスクトップからのファイル削除は完全削除となる。</div><div><br /></div><div>VHDは起動時にはまだマウントされていないため、起動時に他のUSBメモリが装着されているような場合、若いドライブレターが先に適用される。そのためVHDのドライブレターはD、Eなど他のメモリに使われる可能性があるものは避ける。私はVを割り当てることにした。</div><div><br /></div><div><b>方法2</b></div><div>ディスク管理を使用し、USBメモリのパーティションをCドライブ上の空のフォルダにマウントする。</div><div><br /></div><div>アプリケーション インストール先をこのフォルダ下に設定すると、インストールは完了し起動するが、アンインストール、修復で失敗した。何か設定に問題があったのかもしれない。</div><div><br /></div><div>もし試す場合は、バックアップからの復旧か再インストールの準備をしておくこと。</div><div><br /></div><div>もしアプリ削除で問題が発生したら、USBメモリに移動したライブラリ類を標準に戻して、アプリ削除/再インストールを試みる。それでもダメだとバックアップへの復旧か再インストールとなる。</div><div><br /></div><div><div><b>方法3</b></div><div>USBメモリに(例えば)”C:\Program Files (USB)”フォルダを作り、次のコマンドでCドライブにリンクを作る。</div><div>>mklink /J "C:\Program Files (USB)" "D:\Program Files (USB)"</div></div><div><br /></div><div>アプリケーション インストール先をこのフォルダ下に設定する。インストールは完了し起動し、アンインストール、バージョンアップも成功した。</div><div><br /></div><div>VHDマウントのタイムラグの問題がないため、この方が良い場合がありそう。</div><div><br /></div><div><b>方法4</b></div><div>USBメモリ上のフォルダを共用にし、ネットワークドライブに割り当てる。</div><div>このドライブはファイル履歴の保存先として選択可能になる。</div><div>あまり好ましく思えなかったので、よく試していない。</div><div><br /></div><div><div>--------------------</div><div><div><b>レベル3</b></div><div><b>肥大化するフォルダ、サイズの大きいフォルダをUSBメモリへ移動する</b></div></div></div><div><div><div>多くのフォルダアクセスで管理者権限が必要となる。以下の手順でアクセス拒否が発生した場合は、管理者権限でCMD.EXEを起動し、コマンドで操作する。</div><div>また、USBメモリへのデータコピーは属性保存のため、原則としてrobocopyを使用した。</div><div>アプリケーション起動後に残る常駐プロセスのためにフォルダはリネームができない場合がある。その場合は再起動直後に行う。</div><div>バックグランドの常駐サービスが使用しているためにリネームができない場合がある。その場合は回復の再起動でコマンドプロンプトを表示し、リネームした。</div></div><div><br /></div><div><b>バックアップを作っておく</b></div><div><div>不具合が発生した場合、最悪Windows再インストールの可能性もある。</div><div>これ以降に進む前に、バックアップを作っておいた方がよい。</div></div><div><br /></div><div>仮想ハードディスクもバックアップ対象のドライブとして選択可能になるが、USBメモリはWindowsバックアップに含めず、別にrobocopyでコピーする。試していないが、再起動不可の場合はVHDドライブのマウントもできていないので、復元に失敗すると思う。</div><div><br /></div><div>また、USBメモリにライブラリなどのフォルダを移動するためか、システムイメージは作成できるが、ファイルのバックアップには失敗する。</div><div><br /></div><div><div><b>ページングファイルの縮小</b></div><div>メインメモリが不足するとPagefile.sysに書き込まれ、肥大化する。</div><div>固定HDDがある場合などは別ドライブにPagefile.sysを移すことができるが、USBメモリの場合は単純にはできない。</div><div>VHDをPagefile.sysにすることはできるが、Cドライブは使用せずVHDだけにPagefile.sysを作る設定だと、おそらく起動時にはまだマウントが完了していないためCドライブにPagefile.sysが作られた。</div><div>そこで、CドライブにPagefile.sysに200Mを固定で割り当て、VHDにPagefile.sysシステム管理で設定した。今のところこれで動作している。</div><div><br /></div><div>参考:<a href="https://www.teradas.net/archives/13850/" target="_blank">Windowsページングファイル「Pagefile.sys」を縮小する方法</a></div></div><div><br /></div><div><div><div><b>AppDataの</b><b>OneDrive移動</b></div><div><div>C:\Users\<i>username</i>\AppData\Local\Microsoft\OneDrive</div><div><ul><li>OneDriveのリンクを解除する、終了<br />タスクトレイのOneDriveアイコン⇒設定アイコン⇒「設定」クリック<br />⇒「このPCのリンク解除」クリック<br />⇒「OneDrive終了」クリック</li><li>OneDriveのデータコピー<br />>cd C:\Users\<i>username</i>\AppData\Local\Microsoft<br />>robocopy OneDrive D:\...\OneDrive /MIR</li><li>OneDriveリネーム<br />>cd C:\Users\<i>username</i>\AppData\Local\Microsoft<br />>ren OneDrive OneDrive~</li><li>リンク作成<br />>mklink /J OneDrive D:\...\OneDrive</li><li>OneDrive再設定<br /> [スタート] ⇒[検索] ⇒[OneDrive] と入力⇒検索結果で [OneDrive] を選択<br />参考:<a href="https://support.microsoft.com/ja-jp/office/onedrive-%E3%81%AE%E5%90%8C%E6%9C%9F%E3%81%AB%E9%96%A2%E3%81%99%E3%82%8B%E5%95%8F%E9%A1%8C%E3%82%92%E8%A7%A3%E6%B1%BA%E3%81%99%E3%82%8B-0899b115-05f7-45ec-95b2-e4cc8c4670b2?redirectSourcePath=%252fja-jp%252farticle%252fOneDrive-8b-83ab0d8a-8400-45b0-8dcf-dc8aa8a6bcf8" target="_blank">OneDrive の同期に関する問題を解決する</a></li><li>再起動、動作確認後、リネーム後のOneDrive~を削除</li></ul></div></div></div><div><div><div><b>AppDataの</b><b>Edge移動</b></div><div></div><div>C:\Users\<i>username</i>\AppData\Local\Microsoft\Edge</div><div>「AppDataのOneDrive移動」と同様の手順でEdgeをコピー、元フォルダをリネーム、リンク作を行い、Edgeの動作に問題なければ元データを削除する。</div></div><div>Edgeが起動していなければ成功したが、再起動直後に行った方が確実。</div></div><div><br /></div><div><div><b>AppData</b><b>のGoogle移動</b></div><div>Chromeをインストールした場合に実行。</div></div><div><br /></div><div><div>--------------------</div><div><b>レベル4</b></div></div><div>危険度の高いフォルダ移動。</div><div>インストールされたアプリを移動する場合、USBメモリに異常が発生するとアプリのアンインストールができなくなる恐れがある。移動後、速やかにUSBメモリのバックアップを取る。</div><div><br /></div><div><b>SoftwareDistributionの移動</b></div><div>WindowUpdateでフォルダが肥大化するため、”C:\Windows\SoftwareDistribution”をUSBメモリへ移動する。</div><div><br /></div><div><div>DataStore.edbをコマンドで削除する方法ことで小さくすることができるそうだ。大きくなったらその都度コマンド実行するのも面倒なので、私はSoftwareDistributionを移動した。</div><div>参考:<a href="https://itojisan.xyz/trouble/17261/" target="_blank">削除できる?DataStore.edbファイルが重い時の対処方法 – Windows10</a></div></div><div><ul style="text-align: left;"><li>Windowsアップデートで最新状態にする</li><li>Windowsアップデートを停止する<br />>net stop wuauserv</li><li>管理者権限のcmd.exeでコピー、リネーム、リンク作成<br />>cd C:\Windows<br />>robocopy SoftwareDistribution D:\...\SoftwareDistribution /MIR<br />>ren SoftwareDistribution SoftwareDistribution~<br />>mklink /J SoftwareDistribution D:\Windows\SoftwareDistribution</li><li>Windows Update再開<br />>net start wuaserv</li><li>問題なければリネームしたC:\Windows\SoftwareDistribution~を削除<br /></li></ul></div><div>SoftwareDistribution移動後にWindows Updateでエラーが発生したら、SoftwareDistributionを削除する。</div><div><br /></div><div><b>Program Files (x86)の</b><b>Edge移動</b></div><div>「AppDataのEdge移動」と同様の手順で以下のフォルダを移動。</div><div><ul style="text-align: left;"><li>C:\Program Files (x86)\Microsoft\Edge</li><li>C:\Program Files (x86)\Microsoft\EdgeCore</li><li>C:\Program Files (x86)\Microsoft\EdgeUpdate</li><li>C:\Program Files (x86)\Microsoft\WebView</li><li>C:\Program Files (x86)\Microsoft\Temp</li></ul></div><div><b>Program FilesのGoogle移動</b></div><div>Chromeをインストールした場合に実行。</div><div><b><br /></b></div><div><b>Program FilesのDell移動</b></div></div><div>SupportAssistをインストールした場合に実行。</div><div>「AppDataのEdge移動」と同様の手順で以下のフォルダを移動。</div><div><ul style="text-align: left;"><li>C:\Program Files\Dell</li></ul>(リネームに失敗したら回復⇒再起動⇒詳細⇒コマンドプロンプ⇒コマンド実行)</div><div><br /></div><div>--------------------</div><div><b>レベル5</b></div></div><div><b>HDD用空きスペースの利用</b></div><div><a href="https://www.dell.com/community/Storage-Drives-Media/How-to-install-SSD-for-Inspiron-14-3452/td-p/4719538" target="_blank">How to install SSD for Inspiron 14 3452?</a>で紹介されている。</div><div><br /></div><div>外付けHDD/SSDを使用するのがアプリインストール、バックアップなども含めて用途的にはUSBメモリより望ましい。SSDをUSB3.0に接続すると、CrystalDiskMarkの測定では内蔵eMMCの3倍近い速度がでた。</div><div><br /></div><div>しかし、常に外付けを繋いでおくのはうっとうしく、軽量ノートパソコンの意味がなくなる。まだ試していないが、HDD用のスペースにSATA-USB変換アダプタを付けた内蔵HDD/SSDを入れ、USBコネクタと結線する。</div><div><br /></div><div>USB2.0の口となら実現できそうだが、それだとHDD/SSDの速度は引き出せない。</div><div>SB3.0は、線の引き回しが難しそうで、ノイズが乗って期待どおりの速度が出ないとか、エラーが発生する可能性がありそう。</div><div><br /></div><div><b>SATAコネクタ追加</b></div><div>マザーボードにはコネクタを取り付けるはずの端子が付いている。果たして実際に動作するかわからないが、腕に自信があり部品が調達できるなら試してみる価値はあるかも。</div><div><br /></div><div>--------------------</div><div><br /></div><div><b>現状のシステム構成</b></div><div>USB3.0にSunDiskの小型USBメモリを常時装着。(Dドライブ)</div><div>VHD.vhdフォルダを作成し、V:ドライブにマウント。</div><div>D、VにUser、Windowsなどの移動対象のフォルダを原則同じパスになるように設定。</div><div>ライブラリ類は移動時に新規作成してくれる。</div><div><br /></div><div>Vドライブにはvhdマウントのタイムラグを許容できるもので、ファイル削除時にゴミ箱移動にしたいもの(ドキュメントなど)を移動。</div><div><div>Cドライブを圧迫しないよう、新規アプリケーションはVドライブにインストールする。</div></div><div><br /></div><div>Dドライブにはvhdマウントのタイムラグの影響が大きいもの(デスクトップなど)を移動。TEMPなどWindowsが直接操作するものもDドライブへ移動。</div><div><br /></div><div>OneDriveはvhdマウントの影響がでることがあるが、ドキュメントを置く都合でVドライブに移動した。</div><div><br /></div><div>------------------------------</div><div><br /></div><div><div><b>テスト中に利用したコマンド類</b></div></div><div><a href="https://learn.microsoft.com/ja-jp/windows-server-essentials/install/create-a-bootable-usb-flash-drive" target="_blank"><b>ブート可能な USB フラッシュ ドライブの作成</b></a></div><div>試みにUSBメモリをこの方法で初期化してみた。この目的では特に効果なし。</div><div><br /></div><div><div><a href="https://win-plus.net/windows10_explorer_networkdrive_disconnect" target="_blank"><b>Windows10 ネットワークドライブを切断しても消えない場合の対応</b></a></div></div><div>共有フォルダをネットワークドライブに割当たが、それを解除したときにドライブに☓印のついたアイコンが残り、消さなくなった。次のコマンドで解消。</div><div>>net use /PERSISTENT:NO</div><div>直後に再起動</div><div><br /></div><div><b>ディスク使用状況チェック</b></div><div><a href="https://www.vector.co.jp/soft/screen/winnt/util/se475617.html" target="_blank">DiskInfo</a>を使用し、データ量の多いフォルダを探す。</div><div><br /></div><div>------------------------------</div><div><br /></div><div><b>ストレージRead/Writeベンチマーク</b></div><div>CristalDiskMarkによる測定結果</div><div><br /></div><div><b>内蔵eMMC<br /></b></div><div><div class="separator" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEgR98j86w1-Y--rlV5mREeNEtIVUWKUNrm8oRvBIGEriC1CFa6j7LOsfyZmJHe2Z4Gv7HlPC3QirHDJ1z_826vIXJHrsvt4451F1aPo5Vgmjn7mTdLPiLh8zMz5N6bMaS2rEMvHhQCmmF6_2dtynm-DRhofxfkUe_Jg_hO873-1SBfOXL1BHofX3A" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="352" data-original-width="482" height="234" src="https://blogger.googleusercontent.com/img/a/AVvXsEgR98j86w1-Y--rlV5mREeNEtIVUWKUNrm8oRvBIGEriC1CFa6j7LOsfyZmJHe2Z4Gv7HlPC3QirHDJ1z_826vIXJHrsvt4451F1aPo5Vgmjn7mTdLPiLh8zMz5N6bMaS2rEMvHhQCmmF6_2dtynm-DRhofxfkUe_Jg_hO873-1SBfOXL1BHofX3A" width="320" /></a></div><div class="separator" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><b>USB3.0メモリ</b>(SanDisk 64GB Ultra Fit USB 3.1)<br /><a href="https://blogger.googleusercontent.com/img/a/AVvXsEi4qisrFDPSC2StQ6Zo938w8JcAJUDaPxNpde28LIwXigzUPkRYccxBh3pw3L39hqwf1sdDIZFvAOqZRDil8_v3ACPsUDe0_ZVBdNQfE1PLZZir4PDTdhdVa234PD5OMoi0faz5CeL2Hh2Gmdh0sNG0Awee4m1-vxbHe6DPUdZzHiD6PZkdG7EiZA" style="font-weight: bold; margin-left: 1em; margin-right: 1em; text-align: left;"><img alt="" data-original-height="352" data-original-width="482" height="234" src="https://blogger.googleusercontent.com/img/a/AVvXsEi4qisrFDPSC2StQ6Zo938w8JcAJUDaPxNpde28LIwXigzUPkRYccxBh3pw3L39hqwf1sdDIZFvAOqZRDil8_v3ACPsUDe0_ZVBdNQfE1PLZZir4PDTdhdVa234PD5OMoi0faz5CeL2Hh2Gmdh0sNG0Awee4m1-vxbHe6DPUdZzHiD6PZkdG7EiZA" width="320" /></a></div><div class="separator" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: center;"><div class="separator" style="clear: both; text-align: center;">シーケンシャルRWはeMMCに匹敵するが、ランダムアクセスで劣る。</div><div class="separator" style="clear: both; text-align: left;">頻繁にデフラグしておくのが望ましい。</div><div class="separator" style="clear: both; text-align: center;"><br /></div><div class="separator" style="clear: both; text-align: left;"><b>SDカード</b>(SanDisk Extream Pro 64G)</div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEiho4mPA4p1s_sWR2AZK6XLw8M5bFP7qg56IPndKMZo_Ncxu7luLXBvvIfFIkeOcuygmQEFUhPoaTws03XcBJrRHgFJSnPzM5mlKEoI_Xm7I6xwMIT7I4_pHx_WbY5EeWSzyVBY9uZMzvoP2a0bxOpEvpkGCU3WDXAzqRowmHKIrix_HbP4fjWEdQ" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="352" data-original-width="482" height="234" src="https://blogger.googleusercontent.com/img/a/AVvXsEiho4mPA4p1s_sWR2AZK6XLw8M5bFP7qg56IPndKMZo_Ncxu7luLXBvvIfFIkeOcuygmQEFUhPoaTws03XcBJrRHgFJSnPzM5mlKEoI_Xm7I6xwMIT7I4_pHx_WbY5EeWSzyVBY9uZMzvoP2a0bxOpEvpkGCU3WDXAzqRowmHKIrix_HbP4fjWEdQ" width="320" /></a></div><div class="separator" style="clear: both; text-align: left;">USB2.0らしい結果。</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><b>SSD-USB3.0接続</b><br /><div class="separator" style="clear: both; font-weight: bold; text-align: left;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEg3nfi5XFzKZXo8trgIFhSTYbU339s9JVOLtV5N15YBpqV77F0pdX5IDJEiMRVnfctRf4TeNp7v-78Gy4SKBXRFdu-O3WFyBxFFdGQjKJki7wWwr3W6830YapUb_xqAoABP0yD0khJ-nlpY7whjmKXHmX68i6Kp5JcchpBKlTiWL1zUS_1-H4utbQ" style="margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="352" data-original-width="482" height="234" src="https://blogger.googleusercontent.com/img/a/AVvXsEg3nfi5XFzKZXo8trgIFhSTYbU339s9JVOLtV5N15YBpqV77F0pdX5IDJEiMRVnfctRf4TeNp7v-78Gy4SKBXRFdu-O3WFyBxFFdGQjKJki7wWwr3W6830YapUb_xqAoABP0yD0khJ-nlpY7whjmKXHmX68i6Kp5JcchpBKlTiWL1zUS_1-H4utbQ" width="320" /></a></div><div class="separator" style="clear: both; text-align: left;">さすがに速いが外付けなので採用せず。</div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><b>SSD-USB2.0接続</b></div><div class="separator" style="clear: both; text-align: left;"><div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/a/AVvXsEj7NoU4aVLxxEzJ4Lf1lPoYPFEbTV4mX4Ri0INNLEnsyEj0_6qPm4iU1c2FzWg14bk_HTbyAKif6qkstmpvyJRG2zJWfAfZYnjVszL7nJy0hPN6Ht0GwEWONF96RUv3rIYldyx81segiz_VdvFDkyAUGSMHI-WHVxlemiG9hS9OuceyDopBzuE19w" style="font-weight: bold; margin-left: 1em; margin-right: 1em;"><img alt="" data-original-height="352" data-original-width="482" height="234" src="https://blogger.googleusercontent.com/img/a/AVvXsEj7NoU4aVLxxEzJ4Lf1lPoYPFEbTV4mX4Ri0INNLEnsyEj0_6qPm4iU1c2FzWg14bk_HTbyAKif6qkstmpvyJRG2zJWfAfZYnjVszL7nJy0hPN6Ht0GwEWONF96RUv3rIYldyx81segiz_VdvFDkyAUGSMHI-WHVxlemiG9hS9OuceyDopBzuE19w" width="320" /></a><br />SSDでもUSB2.0では価値がない。</div></div></div></div></div></div><div><div><br /></div></div><div><br /></div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-24354616804601632562022-09-03T22:24:00.002+09:002022-10-02T12:11:30.892+09:00Windows 10 ディスク領域が不足でのバックアップ失敗<p><span style="color: #444444;"> メインのマシンをWindows 11にしたので、いささか古いサブマシンにWindows 10をインストールした。いちおう完了したのでバックアップを作ろうとしたら<span face="Arial, "sans-serif"">「ディスク領域が不足しているため、バックアップに失敗しました」が発生した。</span></span></p><p><span face="Arial, sans-serif"><span style="color: #444444;">十分ディスク容量はあるのにおかしいなあ、と思いながらもパティション構成を変えたりして何度かためしたが、相変わらず同じエラーで失敗する。</span></span></p><p></p><ul style="text-align: left;"><li><span style="color: #444444;">ディスク領域が不足しているため、保存場所にボリュームのシャドウコピーを作成できません…</span></li><li><span style="color: #444444;">重要なボリュームの1つに十分な空き領域がないため、システムイメージのバックアップをスキップしました。</span></li></ul><p></p><p><span style="color: #444444;"><span face="Arial, "sans-serif"" style="background-color: #f7f7f7;">などといったメーセージが出るが、何が悪いのかよくわからない。</span><span face="Arial, "sans-serif"" style="background-color: #f7f7f7;">ググってみても未解決のQ&Aか、ディスクの空き容量を増やして成功したというものばかり。</span></span></p><p><span style="color: #444444;">「重要なボリュームの1つ」ということでバックアップ対象を眺めてみると、システム予約のパティション管理領域もボリュームの1つに含まれている。256GのSSDのためか、この領域が50mbと小さく、残り容量がわずかだった。そこで、これをAOMEI Partition Assistant Standard(無料版)で150mbほどに増やして再度試みたところ、成功した。</span></p><p><span style="color: #444444;">解決したあとで改めてググってみると</span></p><h1 class="title lg blk xl_large" data-v-7532355c="" data-v-b75da168="" style="background-repeat: no-repeat; box-sizing: border-box; line-height: 1.4; margin: 16px 0px 0px; overflow-wrap: break-word; padding: 0px;"><span style="color: #444444; font-size: small;"><a href="https://okwave.jp/qa/q8675779.html" style="font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", "Hiragino Kaku Gothic ProN", "Hiragino Sans", Arial, Meiryo, sans-serif; letter-spacing: 0.04em;">PCバックアップエラー</a><br /><span face="-apple-system, BlinkMacSystemFont, Helvetica Neue, Segoe UI, Hiragino Kaku Gothic ProN, Hiragino Sans, Arial, Meiryo, sans-serif"><span style="letter-spacing: 1.28px;"><a href="https://okwave.jp/qa/q8675779.html">https://okwave.jp/qa/q8675779.html</a></span></span></span></h1><p><span style="color: #444444;">というQ&Aで「<span face="-apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", "Hiragino Kaku Gothic ProN", "Hiragino Sans", Arial, Meiryo, sans-serif" style="font-size: 16px; white-space: pre-wrap;">原因:100MBのシステム領域の空き容量不足</span>」と回答されていた。</span></p><p><span style="color: #444444;">というわけで、私の場合は「</span><span style="color: #444444;">重要なボリュームの1つ</span><span style="color: #444444;">」というのが</span><span style="color: #444444;">システム予約のパティション管理領域でした。</span></p><p><span style="color: #444444;">ついでなので、</span><span style="color: #444444;">AOMEI AOMEI Partition Assistant Standardを使って対処する場合につまづいた点について補足しておく。</span></p><p></p><ul style="text-align: left;"><li><span style="color: #444444;">Partition Assistant Standardでディスク先頭の管理領域の右隣のパティションを右クリック</span></li><li><span style="color: #444444;">「パティションサイズをリ</span><span style="color: #444444;">サイズ/移動」をクリック</span></li><li><span style="color: #444444; text-decoration-line: underline;">パティションの先頭に丸アイコンがない場合は</span><span style="color: #444444;"><u>「このパティションを移動したい」をチェック</u>(これがつまづきポイント)</span></li><li><span style="color: #444444;">先頭位置の丸アイコンをドラッグして先頭(左側)に空き領域を作る<br />(サイズの上下アイコンクリックでサイズ微調整が可能)<br /></span></li><li><span style="color: #444444;">ディスク先頭の管理領域を右クリック</span></li><li><span style="color: #444444;">右端の丸アイコンのドラッグ(または</span>サイズの上下アイコンクリック)で領域拡張</li><li>「適用」クリックでリサイズ実行<br /></li></ul><div>パティションリサイズ後にCHKDSKで異常がないか確認するとよいでしょう。</div><div><br /></div><div>もちろん、管理領域以外にもバックアップ対象のボリュームで空き容量が少ないものがあったら、同様の方法でパティションサイズを調整するか、不要なファイル削除などを行う必要があります。</div><p></p>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-10100494229960567792022-08-22T18:28:00.005+09:002022-09-09T01:41:14.562+09:00WiX ToolSet v3.xでの.NET Frameworkの必須バージョンの追加WiX ToolSet v3.xは.NET Fraomeworkのバージョンチェックのための定義を4.6.2までは含んでいるが、それ以降のバージョンについては定義の追加が必要になる。<br />
<span face="Lato, arial, sans-serif" style="color: #2e2e2e;"><br /><span style="background-color: white; color: #212529;">WiX ToolSetで定義済みの.NETバージョンの場合は、</span></span><span face="Lato, arial, sans-serif" style="color: #2e2e2e;">このページに簡潔な説明がある。</span><br />
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
<span style="font-size: small;"><a href="https://www.mking.net/blog/detecting-dotnet-framework-versions-with-wix">Detecting .NET Framework versions with WiX</a></span></div><div style="background-color: white; box-sizing: border-box; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;"><div style="color: #212529;"><br /></div></div>
<div style="background-color: white; box-sizing: border-box; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;"><span style="color: #212529;">
また、次のQ&AでDOT.NET 4.8の定義を追加して、同様のバージョンチェックを行う方法が紹介されている。<br /></span><a href="https://github.com/wixtoolset/issues/issues/5977"><span style="color: #4c1130;">NetFxExtension should support .net 4.8 </span></a></div><div style="background-color: white; box-sizing: border-box; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;"><div> <?define NetFx480MinRelease = 528040 ?>でNetFx480MinReleaseの名前で値を定義</div><div> </div></div>
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
WiX ToolSetで定義済みの.NETバージョン定義を PropertyRef で<span face=", "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"" style="background-color: white; color: #212529; font-size: 16px;">取得できる。</span></div>
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
例:<PropertyRef Id='WIXNETFX4RELEASEINSTALLED'/></div>
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
参照:<a href="https://wixtoolset.org/documentation/manual/v3/howtos/redistributables_and_install_checks/check_for_dotnet.html" style="font-family: Lato, arial, sans-serif;">How To: Check for .NET Framework Versions</a><span face="Lato, arial, sans-serif" style="color: #2e2e2e;">(WiX)</span></div>
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
<br /></div>
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
この値は<span face="Lato, arial, sans-serif">レジストリに登録されている</span><span face="Lato, arial, sans-serif">.NET release keyとなる。</span></div>
<div style="background-color: white; box-sizing: border-box; color: #212529; line-height: 1.2; margin-bottom: 0.5rem;">
参照:<a href="https://docs.microsoft.com/ja-jp/dotnet/framework/migration-guide/how-to-determine-which-versions-are-installed">インストールされている .NET Framework バージョンを確認する</a><span face=""Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif" style="color: #171717;">(Microsoft)</span><span face=""Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif" style="color: #171717;"> </span></div>
<div>
<span face=""Segoe UI", SegoeUI, "Helvetica Neue", Helvetica, Arial, sans-serif" style="color: #171717;"><div><br /></div></span></div>
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
<span face="Lato, arial, sans-serif" style="color: #2e2e2e;">この値と</span><span face="Lato, arial, sans-serif">.NET のバージョンの最小値(</span>NetFx480MinRelease=528040)を比較することで、インストールされている.NET Frameworkが要件を満たしているか判別できる。</div>
<div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;">
例:(上記<a href="https://www.mking.net/blog/detecting-dotnet-framework-versions-with-wix">Detecting .NET Framework versions with WiX</a>より)</div><div style="background-color: white; box-sizing: border-box; color: #212529; font-family: , "blinkmacsystemfont" , "segoe ui" , "roboto" , "helvetica neue" , "arial" , sans-serif , "apple color emoji" , "segoe ui emoji" , "segoe ui symbol"; line-height: 1.2; margin-bottom: 0.5rem; margin-top: 0px;"><br />設定例</div>
<div><span style="font-size: small;"><span style="white-space: pre;">次の例ではWIXNETFX4RELEASEINSTALLED とバージョンの最小値を直接比較する。
</span><div><span style="white-space: pre;"><PropertyRef Id='WIXNETFX4RELEASEINSTALLED'/></span></div><div><span style="white-space: pre;"><Condition Message='This setup requires the .NET Framework 4.7.2 (or greater) to be installed.'></span></div><div><span style="white-space: pre;"> <![CDATA[Installed OR (WIXNETFX4RELEASEINSTALLED >= "#461808")]]></span></div><div><span style="white-space: pre;"></Condition>
次の例ではNetFx480MinReleaseという名前でバージョン番号を定義し、これと比較して</span><span style="white-space: pre;">WIX_IS_NETFRAMEWORK_480_OR_LATER_INSTALLEDの値を設定す</span><span style="white-space: pre;">る。</span></div><div><span style="white-space: pre;"> <?define NetFx480MinRelease = 528040 ?></span></div><div><span style="white-space: pre;"> <PropertyRef Id="WIXNETFX4RELEASEINSTALLED" />
<Property Id="WIX_IS_NETFRAMEWORK_480_OR_LATER_INSTALLED" Secure="yes" />
<SetProperty Id="WIX_IS_NETFRAMEWORK_480_OR_LATER_INSTALLED" Value="1" After="AppSearch">
WIXNETFX4RELEASEINSTALLED >= "#$(var.NetFx480MinRelease)"
</SetProperty></span></div>
</span></div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-46732882759054245142022-08-19T11:55:00.056+09:002022-09-05T10:05:48.526+09:00 自作アプリがウイルス(トロイの木馬)扱いになった ⇒ 解決?<p><span style="color: #444444;"></span></p><p><span style="color: #444444;"></span></p><p><span style="color: #444444;">今度は「Behavior:Win32/Hive.ZY」が見つかった警告された。</span></p><p><span style="color: #444444;">やれやれまたか...で、こんどは自作アプリを疑う前にDefenderに関する書き込みをチェック。すると「窓の杜」からニュースが流れていた。</span></p><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><h1 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: メイリオ, "Hiragino Kaku Gothic ProN", Meiryo, "ヒラギノ角ゴ ProN W3", "ヒラギノ角ゴ Pro W3", "MS PGothic", "MS UI Gothic", Helvetica, Arial, sans-serif; line-height: 1.4; margin: 0px 30px 5px; padding: 8px 0px 0px;"><span style="font-size: small; font-weight: normal;"><a href="https://forest.watch.impress.co.jp/docs/news/1437225.html">マルウェア「win32/hive.zy」が検出されるトラブル ~「Microsoft Defender」ウイルス対策の誤検知か</a></span></h1></blockquote><blockquote style="border: none; margin: 0 0 0 40px; padding: 0px;"><h1 style="background-color: white; border: 0px; box-sizing: border-box; color: #333333; font-family: メイリオ, "Hiragino Kaku Gothic ProN", Meiryo, "ヒラギノ角ゴ ProN W3", "ヒラギノ角ゴ Pro W3", "MS PGothic", "MS UI Gothic", Helvetica, Arial, sans-serif; line-height: 1.4; margin: 0px 30px 5px; padding: 8px 0px 0px;"><span style="font-size: small;"><span style="font-weight: normal;">日本時間(2022年)9月4日より、内部で「Chromium」を利用するアプリ(「Google Chrome」や「Microsoft Edge」、「Spotify」など)を起動するたびに「Microsoft Defender」ウイルス対策が「win32/hive.zy」というマルウェアを検知する現象が発生しているようだ。編集部でも確認をした</span>。</span></h1></blockquote><p>このページのお勧めに従って<span style="background-color: white; color: #333333; font-family: メイリオ, "Hiragino Kaku Gothic ProN", Meiryo, "ヒラギノ角ゴ ProN W3", "ヒラギノ角ゴ Pro W3", "MS PGothic", "MS UI Gothic", Helvetica, Arial, sans-serif; font-size: 16px;">[ウイルスと脅威の防止の更新]を行った。さっそくアップデートがあったようだ。</span></p><p><span style="color: #444444;">------------</span></p><p><span style="color: #444444;">解決と書いたが、しばらくして再発。</span></p><p><span style="color: #444444;">AxWindowsMediaPlayerを使用しており、コントロールを追加するとAxInterop.WMPLib.dll、Interop.WMPLib.dllが追加される。このあたりを疑って試しているうちに、また安定し始めた。</span></p><p><span style="color: #444444;">以前にウイルス扱いとなったバージョンも今は問題ない。</span></p><p><span style="color: #444444;">どうやらDefenderの<span face="arial, sans-serif" style="background-color: white;">定義ファイルが修正されたようだ。</span></span></p><p>------------</p><p>先日「自作アプリがウイルス扱いになったのがWIndows 11再インストールで解決した」と書き込みをしたが、その後システムドライブバックアップ中に検疫にひっかかり、再度トロイの木馬扱いとなった。</p><p>ソースコードで関連ありそうなメソッド呼び出し順次止めて試したところ、Assemblyからcopyrightの文字列を取得している箇所を削除することで検疫をパスするようになった。</p><div><div>Attribute copyright = Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(System.Reflection.AssemblyCopyrightAttribute));</div></div><div><br /></div><div>ただし、このメソッド呼び出しは別アプリでも使用しており、なにかしら別要因との組み合わせがあると思われる。</div><p>------------</p><p>2022年8月初旬に自作アプリ(RenameMe)がトロイの木馬(Trojan:Script/Wacatac.H!ml)扱いになって、Defederで検疫されてしまった。</p><p>表示されたダイアログをコピーしておかなかったが、次のようなメッセージが表示され、挙句Defenderから脅威が見つかったと警告された。</p><p>・This applicaion could not be started.<br />・このアプリを実行すると、PC に問題が起こる可能性があります。</p><p>アプリ本体はDOT.NETのライブラリとメディアプレーヤのWMPLibで、いずれもMicrosoft製のものしか使用していない。</p><p>インストーラはオープンソースのWixTookSetを利用しているが、これはMicrosoft製のツールを引き継いだもので、<span face="arial, sans-serif" style="background-color: white;">Windows Installer (MSI) パッケージを作成するが実際のインストールはWindowsの機能で行うものだ。また、インストールしたアプリだけでなくReleaseビルドしたexeを起動しても「</span>このアプリを実行すると、PC に問題が起こる可能性があります。」となるのでインスーラは関係なさそう。</p><p>今まで動いていたものを突如トロイの木馬扱いにするのだから、これは誤検知に相違ないのだが、といってアプリが動かないのは困る。</p><p>まずはアプリをビルドしなおしてみる。やはりダメなので次のことを順次試して、アプリケーションの削除/インストールを繰り返してみる。</p><p>・DOT.NETのバージョンを4.7.2から4.8に上げる<br />・WixTookSetを3.11.2に上げる</p><p>DOT.NET Framework4.8の再インストールを試みるが、これは既にインストール済みと拒否される。</p><p>これでも同じ現象が続くので、Windows Updateで更新状態をチェックすると、KB5016629のインストール待ち状態だった。これのインストールを試みるが失敗。</p><p>次のようなコマンドを実行するがエラーで成功しない。</p><p>dism /Online /Cleanup-Image /ScanHealth<br />dism /online /cleanup-image /startcomponentcleanup<br />sfc /scannow</p><div>エラーメッセージは次のようなもの。</div><div>・指定したバッファーに誤った形式のデータが含まれています。</div><div><div>・Windows リソース保護は要求された操作を実行できませんでした。</div></div><div><br /></div><div>当然ながらWindows Updateは再度失敗。<br />オフライン更新も試みるが同じエラーで失敗。</div><p>いささか行き詰まり状態になり、復元ポイントやバックアップで前の状態に戻すことを考え始めたが、Window 11では個人データだけでなくアプリも残したのまま上書きインストール可能というのを発見し、これを試みることにする。Windows 10でも上書きインストールできたんですね。</p><h1 style="border: 0px; color: #333333; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; letter-spacing: 1px; line-height: 38.4px; margin: 0px 0px 0px 20px; padding: 0px; vertical-align: baseline;"><span style="font-size: small;">参照: <a href="https://www.pasoble.jp/windows/11/uwagaki-reinstall.html">Windows11 上書きインストールで現状を全て保持して修復</a></span></h1><div class="lastUp" style="border: 0px; color: #aaaaaa; font-size: 12px; font-stretch: inherit; font-variant-east-asian: inherit; font-variant-numeric: inherit; letter-spacing: 1px; line-height: 18px; margin: 12px 0px 0px; padding: 0px; text-align: right; vertical-align: baseline;"></div><p>isoをダウンロードしインストールを開始すると、なんとTPM2.0が有効になっていないという。UEFI(BIOS)画面でチェックすると、確かに無効になっていた。しばらく前にBIOSをアップデートしたので、そのときに初期状態に戻っていたようだ。Windows 11はTPM2.0必須ではあるが、インストール後これが無効でも起動するのですね。</p><p>ついでに高速スタートアップが無効になっていることを確認。</p><p>TPM2.0を有効にし、再度上書きインストールを試み、成功。</p><p>再起動後にWindows Updateを見るとKB5016629の前のKB5015732、KB4023057も待ち状態になっていた。</p><p>KB4023057は「<span face=""Segoe UI", "Segoe UI Web", wf_segoe-ui_normal, "Helvetica Neue", "BBAlpha Sans", "S60 Sans", Arial, sans-serif" style="background-color: white; color: #1e1e1e; font-size: 16px;">.NET Framework 3.5 および 4.8 の累積的な信頼性の向上が含まれています</span>」となっており、どうもこれが関係しているように思われる。</p><p>その後、アプリを再ビルド、再インストールし、今のところ安定して動作している。<br />⇒その後システムドライブ バックアップ時に再発</p><p>振り返ってみると、つぎのような順序で問題が発生したのではないかと思われる。</p><p>・しばらく前にWindowsの動作が重くなり、BIOSのアップデートを行った。(実際はBIOSの問題ではなくIMEをGoogle日本語入力に置き換えることで解決した。)</p><p>・BIOSアップデート時に設定が初期化され、TPM2.0がオフになった。</p><p>・Windows 11は動作しつづけたが、もしかしたらTPM2.0オフが一因でWindows Updateで更新失敗が発生。もしかしたらDOT.NET 4.8が関係してウイルス検知を誘発。</p><p>・KB5015732、KB4023057いずれかの更新失敗のため、KB5016629も更新失敗。</p><p>・このときのゴミでdism、sfcコマンドでもエラーが発生。</p>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-45524934046899455742022-07-27T11:08:00.003+09:002022-09-04T06:06:42.162+09:00IMEが原因でWindows 11 がえらく重くなった<p>しばらく前からWindows 11 の動作がえらく重くなった。</p><p>特にIMEの動作が遅くなった。キー入力後に漢字変換の候補が出るまでに、時には数秒待たされることもあった。タスクバーのIMEアイコンが☓になり、「IMEが無効です」となったりした。</p><p>IMEが全く反応しないこともあったが、これはIMEの設定で以前のバージョンに戻すことで改善はしたものの、もたつきは相変わらずだった。また、IMEアイコンは出ても右クリックに反応せず、コンテキストメニューが表示されないことがあった。</p><p><span face=""Noto Sans JP", メイリオ, "ヒラギノ角ゴ Pro W3", "Hiragino Kaku Gothic Pro", Meiryo, Osaka, "MS Pゴシック", "MS PGothic", sans-serif" style="background-color: white; color: #333333; font-size: 15.9992px;">ctfmon.exeを手動で実行しても変化がない。タスクマネージャで動作をチェックすると、一瞬現れるがすぐに消えたりする。</span></p><p>ビデオ編集にVideoStudioを使っているが、マウスドラッグがスムーズに行えなくなったりもした。このせいで、IMEというよりもWindowsそのものや、ハードになにか問題がありそうに思えた。</p><p>もともとメモリにちょっと問題があったこともあり、BIOSやドライバをアップデートしたり、またWindowsを少し前の復元ポイントに戻したりもしたが、改善されない。</p><p>ウイルスも疑い、defenderでフルスキャンをしたが、特に問題は見つからない。</p><p>IMEの設定で予測変換をOFFにすると若干よくはなったようだが、やはり我慢できないほどもたつく。</p><p>などなど、さんざんに試した挙げ句、Googleの日本語入力に置き換えてみると、入力はさくさくできるようになり、VideoStudioの動作も元にもどった。</p><p>"Windows 11 ime 不具合"といったキーワードで検索すると結構出てくるので、IMEの不具合自体は珍しいことではないようだ。それでも、そのせいで他のアプリのマウス操作にまで影響がでるのは驚きだ。</p><p>しばらくはGoogle日本語入力を使い続けることになりそうだ。</p>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-80550243340792222862022-03-28T18:08:00.004+09:002022-09-04T06:05:54.687+09:00Windows関連メモ<div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;"><b>Windiws 11 で Windows セキュリティーが開かない</b></span></div><div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;">アップグレード後にフルスキャンをしておこうと思ったら</span><span style="color: #333333; font-size: 16.32px;">Windows セキュリティーが開かない。</span></div><div><span style="color: #333333; font-size: 16.32px;">次のリンクの方法で、とりあえず起動するようにできた。コマンドの意味が書いてなく、まだ調べていないので他のアプリへの影響などはわからない。</span></div><div><ul style="text-align: left;"><li><span face="-apple-system, BlinkMacSystemFont, "Helvetica Neue", "Segoe UI", "Hiragino Kaku Gothic ProN", "Hiragino Sans", Arial, Meiryo, sans-serif" style="background-color: white; color: #222222; letter-spacing: 0.04em;"><a href="https://note.com/fu_min906/n/ne2b2591c2f4d" style="font-weight: bold;">Windows11 でWindowsセキュリティが開けない時の対処法</a>(ふーみん)</span></li></ul></div><div><span style="color: #222222;"><span style="letter-spacing: 0.64px;">手順</span></span></div><div><ul style="text-align: left;"><li><span style="color: #222222;"><span style="letter-spacing: 0.64px;">すべてのアプリを終了した状態(アイドル状態)</span></span></li><li><span style="color: #222222;"><span style="letter-spacing: 0.64px;">Windows PowerShell を<span style="--tw-ring-color: rgb(59 130 246/0.5); --tw-ring-offset-color: #fff; --tw-ring-offset-shadow: 0 0 transparent; --tw-ring-offset-width: 0px; --tw-ring-shadow: 0 0 transparent; --tw-rotate: 0; --tw-scale-x: 1; --tw-scale-y: 1; --tw-scroll-snap-strictness: proximity; --tw-shadow-colored: 0 0 transparent; --tw-shadow: 0 0 transparent; --tw-skew-x: 0; --tw-skew-y: 0; --tw-translate-x: 0; --tw-translate-y: 0; background-color: white; background-repeat: no-repeat; border: 0px solid; box-sizing: inherit; font-family: YakuHanJPs, "Segoe UI", Arial, Meiryo, sans-serif; font-size: 18px; letter-spacing: normal; margin: 0px; padding: 0px;">管理者権限で起動</span></span></span></li><li><span style="background-color: white; color: #222222; font-family: YakuHanJPs, "Segoe UI", Arial, Meiryo, sans-serif; font-size: 18px;">コマンド実行<br />Get-AppxPackage Microsoft.SecHealthUI -AllUsers | Reset-AppxPackage</span></li><li><span style="background-color: white; color: #222222; font-family: YakuHanJPs, "Segoe UI", Arial, Meiryo, sans-serif; font-size: 18px;">Windows セキュリティを起動、動作確認</span></li></ul></div><div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;"><b>Windows 11 コマンドでシステム>電源を開く</b></span></div><div><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><span style="background-color: white; font-size: 16.32px;">ディスプレイの電源OFF、スリープまでの時間設定のダイアログにたどり着くに多くの手数が必要。次の要領で</span></span><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="color: #333333; font-size: 16.32px;">システム>電源へのショートカットを作れる。</span></div><div><ul style="text-align: left;"><li>画面の空白部分を右クリック > 新規作成 > ショートカット</li><li>[項目の場所を入力してください]に"ms-settings:powersleep"を設定</li><li>[次へ]クリック</li><li>[このショートカットの名前を入力してください]に(例えば)"電源スリープ"を設定</li><li>[完了]クリック</li></ul>デスクトップにショートカットアイコンが作成される。</div><div><ul style="text-align: left;"><li><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><span style="font-size: 16.32px;"><b><a href="https://docs.microsoft.com/ja-jp/windows/uwp/launch-resume/launch-settings-app#personalization">Windows 設定アプリの起動</a>(Microsoft)</b></span></span></li><li style="font-size: 16.32px; font-weight: bold;"><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><a href="https://www.ipentec.com/document/windows-10-open-settings-window-using-command">コマンドを実行して設定画面を開く (Windows 10 Tips)</a></span></li><li><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><b><a href="https://atmarkit.itmedia.co.jp/ait/articles/1804/26/news035.html">コントロールパネルの[システム](相当)や[システムのプロパティ]を素早く開く方法</a></b></span></li></ul></div><div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;"><b><br /></b></span></div><div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;"><b>Windows 11 エクスプローラの行間を狭くする(以前と同じにする)</b></span></div><div><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><span style="background-color: white; font-size: 16.32px;">ファイルエクスプローラーの行間が広くなって表示項目数が減ってしまった。</span></span></div><div><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><span style="background-color: white; font-size: 16.32px;">エクスプローラ > 表示 > コンパクトビュー で行間を以前と同じように狭くできる。</span></span></div><div><span style="background-color: white;"><div><ul style="text-align: left;"><li><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><b><a href="https://faq.mypage.otsuka-shokai.co.jp/app/answers/detail/a_id/312597/~/%5Bwindows11%5D-%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%97%E3%83%AD%E3%83%BC%E3%83%A9%E3%83%BC%E3%81%AE%E8%A1%8C%E9%96%93%E3%82%92%E7%8B%AD%E3%81%8F%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95%EF%BC%88%E3%82%B3%E3%83%B3%E3%83%91%E3%82%AF%E3%83%88%E3%83%93%E3%83%A5%E3%83%BC%EF%BC%89">エクスプローラーの行間を狭くする方法(コンパクトビュー)</a></b></span></li><li><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><span style="font-size: 16.32px;"><b><a href="https://ex1.m-yabe.com/archives/5872">エクスプローラーで詳細表示の行間を狭くする</a></b></span></span></li></ul></div></span></div><div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;"><b><br /></b></span></div><div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;"><b>アクティブなウインドウのディスプレイ切替</b></span></div><div><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;">マルチディスプレイ環境でディスプレイの接続が切れると、そこにあったウインドウが表示されなくなり困ることがある。そんなときに</span><span face="メイリオ, Meiryo, "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "sans-serif", "MS Pゴシック"" style="background-color: white; color: #333333; font-size: 16.32px;">便利。</span></div><div><span style="background-color: white;"><div><ul style="text-align: left;"><li><span face="メイリオ, Meiryo, Hiragino Kaku Gothic Pro, ヒラギノ角ゴ Pro W3, sans-serif, MS Pゴシック" style="color: #333333;"><span style="font-size: 16.32px;"><b><a href="http://menushowdelay.blog.fc2.com/blog-entry-3236.html">誰も教えてくれなかったショートカットキー「Windows+Shift+方向キー」</a></b></span></span></li></ul></div></span></div><b><div><b><br /></b></div>スタートメニューの場所</b><br />
<ul>
<li><b>ユーザ別</b><br />C:\Users\<i>UserName</i>\AppData\Roaming\Microsoft\Windows\Start Menu\Programs</li>
<li><b>全ユーザ共通</b><br />C:\ProgramData\Microsoft\Windows\Start Menu\Programs</li>
</ul><b><div><b><br /></b></div>
Windows MediaPlayer再インストール</b><div>
<ul>
<li>mouseコンピュータ FAQアーカイブ<br /><a href="https://www2.mouse-jp.co.jp/ssl/user_support2/sc_faq_documents.asp?FaqID=5785" style="font-family: "ヒラギノ角ゴシック ProN", "Hiragino Kaku Gothic ProN", メイリオ, Meiryo, "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 16px; font-weight: 700;">Windows Media Player 12 再インストール方法</a><br /><span style="font-size: x-small;">https://www2.mouse-jp.co.jp/ssl/user_support2/sc_faq_documents.asp?FaqID=5785</span></li>
<li><span style="font-size: x-small;">https://www.microsoft.com/en-us/download/details.aspx?id=507</span></li>
</ul>
<div>
<span style="font-size: x-small;"><br /></span></div>
<br />
<br /></div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-28368893157312603362022-02-03T11:59:00.008+09:002022-04-12T14:06:03.096+09:00DIGA DMR-BRT220 電源が落ちる 修理記録<p><span style="font-family: inherit;"> Panasonic DIGA <span style="background-color: white;">DMR-</span><span style="background-color: white;">BRT220 が故障した。</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;">最初はハードディスクが認識されなくなったと思われたのだが、どうやら電源が数十秒で落ちるようになっていたためらしく、</span></span><span style="background-color: white; font-family: inherit;">最終的には冷却ファンを掃除することで直ってしまった。とはいえ、そこまでたどり着くのに結構手間暇かかったので、ちょっとまとめておく。</span></p><p><span style="background-color: white;"><span style="font-family: inherit;">まずは録画済みの番組をなんとか復活できあいものかと試みたが、これは残念ながら失敗してしまった。これについては後ほど補足する。</span></span></p><p><span style="background-color: white;"><span style="font-family: inherit;">もともとのハードディスクと同じモデルのものを購入、換装することで動作するように見えたが、30秒程で電源が落ちてしまう。</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;">最初に見つけたのはこのページ</span></span></p><p><span style="font-family: inherit;"><span style="background-color: white;"><a href="https://jimnysj.blog.fc2.com/blog-entry-3109.html">電気屋さんのお仕事 パナソニックディーガ XW300電源が入らない</a></span><br /></span></p><p><span style="font-family: inherit;">ICプロテクタ(フューズのようなものらしい)が切れると同じ現象になるらしい。<br /></span><span style="font-family: inherit;">このページを参照して、同様の故障を修理した記事もある。</span></p><p><span style="font-family: inherit;"><a href="https://freeride.cocolog-nifty.com/blog/2020/11/post-31df5f.html">検索したらただ乗りだった件</a></span></p><p>DIGAとICプロテクタに関しては、他にもいろいろ見つかる。</p><div><a href="http://himoyo.web.fc2.com/butubutu.htm">★DMR-XW100の修理!?</a></div><div><div><a href="http://se-kimagure.cocolog-nifty.com/blog/2012/05/diga-a968.html">DIGAの修理</a></div></div><div><div><a href="http://fanblogs.jp/hb25/archive/594/0">PanasonicのDVDレコーダー壊れた。の巻</a></div></div><div><div><a href="https://www.tefutefusanpo.net/entry/2018/03/05/220654">故障は突然に…いきなりDVDレコーダーが動かなくなりました…</a></div></div><div><br /></div><div>そこで、分解し基盤を取り出して調べてみる。<span style="background-color: white;">DMR-</span><span style="background-color: white;">BRT220の</span>ICプロテクタについてズバリ書いてある記事は見つからなかったので、それらしいものを探してみる。</div><div>基盤に印刷してある部品名がIPで始まり、四角の中にKとマークしてものが表に二つ、裏にひとつあった。テスタで調べてみるとどれも導通している。う~~む、これのせいではなさそうだ。</div><div><br /></div><div>電源回路のコンデンサが壊れている場合も、同様の現象になるらしい。</div><div><br /></div><div><div><a href="https://blog.nullnuma.com/repair-diga/">DIGAを修理した</a></div></div><div><br /></div><div>この場合には膨れているコンデンサがあるようだが、見ためにはそれらしきものは見当たらない。</div><div><br /></div><div>半ばあきらめつつ他の手がかりを探してみると、<span style="background-color: white;">冷却ファンの故障が原因というのが見つかった。"</span><span style="background-color: white;">ファン"をキーワードに入れるといくつも出てくる。</span></div><div><span style="background-color: white;"><a href="https://minkara.carview.co.jp/userid/329371/blog/39949374/"><br /></a></span></div><div><span style="background-color: white;"><div><a href="https://minkara.carview.co.jp/userid/329371/blog/39949374/">フォーマットしちゃいました</a></div><div><a href="https://bbs.kakaku.com/bbs/K0000216986/SortID=20583635/">『すぐに電源が落ちる(自己解決)』のクチコミ掲示板</a></div><div><div><a href="https://naokit.info/2021/12/14/%E9%9B%BB%E6%BA%90%E3%81%8C%E8%90%BD%E3%81%A1%E3%82%8B%E3%83%91%E3%83%8A%E3%82%BD%E3%83%8B%E3%83%83%E3%82%AF%E3%81%AEbd%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%80%E3%83%BC%E3%82%92%E4%BF%AE%E7%90%86/">電源が落ちるパナソニックのBDレコーダーを修理してみた – DMR-BRW1000 –</a></div></div><div><br /></div><div>電源を入れてみると、ファンが一瞬回るがすぐ止まる。これが正常な動作なのか分からない。埃を取って、指で回したりを何度か繰り返しているうちに回るようになった。すると、電源も入ったままになり、なんと直ってしまった。</div><div><br /></div><div>ということで、電源がすぐに落ちてしまう現象が発生したら、まずはファンが回転しているかチェック。回転していない、あるいは不安定ならファンの<span style="font-family: inherit;">掃除を念入りに行う。</span><span style="font-family: inherit;">精密</span><span style="font-family: inherit;">機械用</span><span style="font-family: inherit;">潤滑油</span><span style="font-family: inherit;">をさすのもよさそうです。</span></div><div><span style="font-family: inherit;"><br /></span></div><div>参考リンク</div><div><div><span style="color: #0000ee;"><u><a href="https://readymade-net.com/440/diga-replacement-hdd/">Panasonic DIGA 換装用 AVコマンド対応・低発熱のハードディスク(HDD)選び</a></u></span></div><div><a href="https://readymade-net.com/440/diga-hdd-%e6%8f%9b%e8%a3%85-%e3%83%87%e3%83%bc%e3%82%bf%e5%87%a6%e7%90%86%e3%81%ae%e9%9a%9b%e3%81%ae%e5%80%a42016%e5%b9%b47%e6%9c%88%e7%89%88/">DIGA ハードディスク(HDD) 換装 データ処理の際の値(2016年7月版) 500G~8TBまで網羅</a></div></div><div><br /></div><div><span style="font-family: inherit;"><br /></span></div><div>それでもだめなら、ICプロテクタや電源回路のコンデンサを疑いましょう。<br /></div><div><br /></div></span></div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-10243590575066145242021-06-14T19:04:00.013+09:002022-09-04T06:12:02.651+09:00C# TagLib#でwavファイルのタグを設定する方法<p>TagLibでmp3のタグ編集アプリを作りつつ、ついでにwavのタグ設定を試してみました。</p><p>mp3で文字化けに悩まされたましたが、wavでもやはり発生しました。</p><p>wavの場合の問題は、WindowsはwavのタグをShift-JISで読み書きするのに対し、TagLibはUTF8で読み書きすることです。</p><p>TagLibはファイルから読み込んだバイト列をByteVectorオブジェクトに格納し、これをAPIを介してStringにしています。</p><p>なので、そのAPIを介さずに、TagLibが保持しているバイト列をShift-JIS EncodingでString化し、Saveする前にバイト列を直接セットすれば文字化けを回避できます。</p><p>TagFileを作るときはファイルの種類を意識する必要はありません。</p><p><span> </span>TagLib.File TagFile = TagLib.File.Create(FilePath);</p><p>TagFileからTagを取得するときは、TagLib.TagTypes.RiffInfoを使います。</p><p><span> </span>TagLib.Riff.InfoTag tag = TagFile.GetTag(TagLib.Riff.InfoTag, true);</p><p>次の要領でShift-JIS Endodingでバイト列をString化します。</p><p><span> </span>Encoding SjisEnc = System.Text.Encoding.GetEncoding("shift-jis");<br /> String GetStringFromSjisPropery(TagLib.Riff.InfoTag tag, TagLib.ByteVector id)<br /> {<br /> TagLib.ByteVectorCollection vals = tag.GetValues(id);<br /> foreach (TagLib.ByteVector v in vals)<br /><span><span> </span> </span>{<br /><span><span> </span> </span><span> </span>byte[] b = v.Data;<br /><span><span> </span> </span><span> </span>if (b.Length > 0)<br /><span><span> </span><span> </span> </span>{<br /><span> </span><span> </span><span> </span>return SjisEnc.GetString(b);<br /><span><span> </span> </span><span> </span>}<br /><span><span> </span><span> </span></span>}<br /><span><span> </span> </span>return null;<br /><span> </span>}</p><p>Artist, Album, Titleのidは次のようになります。</p><p><span> </span>ByteVector idArtist = new ByteVector(Encoding.ASCII.GetBytes("IART"));<br /><span> </span>ByteVector idAlbum = new ByteVector(Encoding.ASCII.GetBytes("IPRD"));<br /><span> </span>ByteVector idTitle = new ByteVector(Encoding.ASCII.GetBytes("INAM"));</p><p>出力時は、save直前にShift-JISでバイト列化したByteVectorを当該項目にセットします。</p><p><span> </span>ByteVector ToByteVector(ByteVector id, String str)<br /><span> </span>{<br /> <span> </span>return new ByteVector(SjisEnc.GetBytes(str+ " "));<br /><span> </span>}</p><p>なぜか文字化けるので、strにスペースを一文字足してからバイト列化しています。<br />(スペースではなくnull('\0')が正しいのかも?)</p><p>StringをByteVectorにしたものを、次の要領でtagにセットします。</p><p><span> </span>((TagLib.Riff.InfoTag)tag).SetValue(id, ToByteVector(id, str));</p><p>uintのTrackなど、String以外の項目はTagLibのAPIで直接操作できます。</p><p>Windows内だけ利用する場合は、これでOKでしょう。他のOS環境や、アプリによっては文字化けるかもしれません。</p><p>[追記]</p><p>Wavのヘッダー仕様はRIFFで定義されていますが、これのTRACKのIDが曖昧です<br /><span face="arial, sans-serif" style="background-color: white;">IPRT</span><span face="arial, sans-serif" style="background-color: white;">, </span><span face="arial, sans-serif" style="background-color: white;">ITRK</span><span face="arial, sans-serif" style="background-color: white;">, TRCKの3つが使われる場合があるようです。<br />TagLibは</span><span face="arial, sans-serif" style="background-color: white;">IPRTで読み書きしていますが、Windowsのエクスプローラは</span><span face="arial, sans-serif" style="background-color: white;">ITRKの値を表示します。</span></p><p><span face="arial, sans-serif" style="background-color: white;">TagLibで</span><span face="arial, sans-serif" style="background-color: white;">ITRKに値のRead/Writeは次のようにします。</span> </p> ByteVector idTrack = new ByteVector(Encoding.ASCII.GetBytes("ITRK"));<div> //Read<br /><div><div> uint trackNum = ((TagLib.Riff.InfoTag)tag).GetValueAsUInt(idTrack);</div><div> //Write<br /> ((TagLib.Riff.InfoTag)tag)<span style="background-color: white;"><span face="arial, sans-serif">.SetValue(</span></span>idTrack<span style="background-color: white;"><span face="arial, sans-serif">, </span></span>trackNum<span style="background-color: white;"><span face="arial, sans-serif">);</span></span><div><p>-------</p><p>ついでながら、TagLibは様々なフォーマットに対応しています。<br />wma、m4a(aac)を試したところ、これらはutf8で問題ないようで、基本的にmp3と同じ要領で読み書きできます。</p><p>TagFile.GetTag(TagLib.TagTypes)の引数に使う定数は次のようになります。</p><p><span> </span>wma: TagLib.TagTypes.Asf<br /><span> </span>m4a: TagLib.TagTypes.Apple</p></div></div></div></div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-87636178425178299372019-12-26T12:15:00.008+09:002022-09-08T12:16:20.841+09:00Windows 10 システムを「バックアップと復元」を使って別ディスク(SSD)へ移行する方法システムディスクをSSDへ移行するにあたり、引っ越しソフトがあればそれを使うのが簡単ですが、ディスクが壊れた時の復旧時にも必要なことなので「バックアップと復元」を使って行なってみました。これが意外と単純ではなかったので、メモしておきます。<br />
<b><br /></b>
「バックアップと復元」でシステム移行を行う場合、移行先ディスクのデータ容量は元ディスクと同じか、大きくなければいけません。<div><br /></div><div>もし小さいディスクへ移行させたい場合はAOMEI Partition Assistantなどを利用し、元システムのパティション構成を変更してからバックアップを作れば対応可能です。<br /><div><br />
<b>移行作業</b><br />
<b><br /></b>
①「バックアップと復元」で「システム修復ディスク」を作成する。<br />
②「バックアップと復元」で「システムイメージ」を作成する。私はシステムディスク(C:)だけのイメージを作成。<br />
③移行先のディスクをdiskpartで完全消去する。<br />
もしかしたら、購入したままのまっさらなディスクならこの作業は不要かもしれない。<br />
これを行なわないと復元実行時に次のエラーが発生する。<br />
データ ディスクが現在 BIOS 上でアクティブに設定されています。その他の<br />
ディスクをアクティブに設定するか、または DiskPart ユーティリティを使用<br />
してデータ ディスクから不要なデータを消去した後で、復元操作を再試行し<br />
てください。<br />
<br />
コマンド実行要領<div>
>diskpart</div><div> DISKPART> list disk </div><div> (表示される一覧からターゲットディスクの番号を探す)</div><div> DISKPART>select disk n</div><div> DISKPART>clean</div><div>
<br />
詳しくはこちらを参照<br />
<a href="http://blog.livedoor.jp/oda_susi/archives/53964463.html"><windows|トラブル|解決済>OSバックアップを復元出来ない</a><br />
<div>
<br /></div>
④現在のシステムディスクを取り外し、移行先のSSDを取り付ける。現在のシステムディスを取り付けたままだとそのディスクが回復対象になり、別ディスクには移行できませんでした。<br />
<br />
⑤「システム修復ディスク」で起動<br />
詳しくはこちらを参照<br />
<a href="http://tanweb.net/2017/11/20/16734/">Windows 10 システムイメージからの復元(戻す)方法を徹底解説</a></div><div>
<div>
<br /></div>
<div>
⑥「イメージでシステムを回復」を実行</div>
<div>
詳しくは⑤のリンクを参照</div><div><br /></div><div>追記</div><div>システム修復時に再起動後ブートできず”<a h="ID=SERP,5539.1" href="https://www.bing.com/search?q=inaccessible+boot+device&FORM=AWRE" style="background-color: white; color: #1a0dab; font-family: Roboto, Helvetica, sans-serif; font-size: 16px; text-decoration-line: none;" wrc_done="true">inaccessible boot device</a><span face="Roboto, Helvetica, sans-serif" style="background-color: white; color: #111111; font-size: 16px;">”エラーでブルースクリーンになった。UEFI(BIOS)のBOOT設定でACHIがIDEに変わっていたことが原因で、</span><span face="Roboto, Helvetica, sans-serif" style="background-color: white; color: #111111; font-size: 16px;">ACHIに変更後、無事再起動できた。</span></div><div>
<br /></div>
<div>
<b>移行先ディスクの回復パティション移動</b></div>
<div>
<br /></div>
<div>
これで別ディスクにシステムが移行ができたのですが、元ディスクに「回復パティション」がある場合、これも含めてまったく同じ場所に復元されてしまいます。より大きなディスクを用意しても、これが邪魔でシステムのパティションを大きくすることができません。</div>
<div>
<div>フリーバージョンのAOMEI Partition Assistantで、パティションをディスクの末尾に移動させることができます。</div><div><br /></div>
</div>
<div>
詳しくはこちらを参照</div>
<div>
<div>
<a href="https://www.disk-partition.com/jp/windows-10/windows-10-move-recovery-partition.html">Windows 10で回復パーティションを移動する方法|データ損失なし!</a></div>
</div>
<div>
<br /></div>
<div>
試していませんが、diskpartを使って回復パティションの移動(削除・再設定)を行う方法が紹介されています。</div>
<div>
詳しくはこちらを参照</div>
<div>
<div>
<a href="https://fortrand.hatenablog.com/entry/2018/04/24/182612">回復パーティションを移動したときの話</a></div>
</div>
<div>
<br /></div>
<div>
回復パティション移動/削除後は、「ディスクの管理」を使ってパティションの拡張が可能です。</div>
<div>
<br /></div>
<b>回復パティションの削除</b><br />
引っ越し完了後にもとのディスクを再利用しようするにあたり「回復パティション」を削除したいが、「ディスクの管理」では表示のみで削除不可なので、diskpartコマンドで削除しました。<br />
「AOMEI Partition Assistant」では、できそうでできませんでした。有償版なら可能かもしれません。<br />
<br />
・コマンドプロンプトを管理者権限で起動<br />
・次の要領でコマンド実行<br />
>diskpart<br />
DISKPART> list disk<br />
ディスク 状態 サイズ 空き ダイナ GPT<br />
### ミック<br />
------------ ------------- ------- ------- --- ---<br />
....<br />
ディスク 3 オンライン 119 GB 118 GB<br />
<br />
DISKPART> select disk=3<br />
ディスク 3 が選択されました。<br />
<br />
DISKPART> list partition<br />
Partition ### Type Size Offset<br />
------------- ------------------ ------- -------<br />
Partition 1 回復 510 MB 118 GB<br />
<br />
DISKPART> select partition=1<br />
パーティション 1 が選択されました。<br />
<br />
DISKPART> delete partition override<br />
DiskPart は選択されたパーティションを正常に削除しました。<br />
<br />
詳しくはこちらを参照<br />
<a href="https://pc-karuma.net/windows-10-delete-recovery-partition-diskpart/">Windows10 - 回復パーティションの削除(DiskPart)</a></div></div></div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-61985173372056328602019-06-11T18:39:00.010+09:002022-10-21T13:26:31.388+09:00C# TagLib#のMP3タグ文字化け対策C#でMP3タグの編集を行うアプリを作るのにTagLib-sharpを使ってみました。<br />
<div>
まずは、こんな簡単にタグを設定できます、といった例が見つかります。</div>
<div>
<br /></div>
<div>
TagLib.File tagFile = TagLib.File.Create(filePath);</div>
<div>
<div>
tagFile.Tag.Title = "My Favorite Things";</div>
<div>
</div>
<div>
<div>
tagFile.Tag.Album = "BEST";</div>
<div>
</div>
<div>
tagFile.Tag.Performers = new string[] { "My Favorite Singer" };</div>
<div>
</div>
tagFile.Save();</div>
</div>
<div>
<br /></div>
<div>
</div>
<div>
確かにこれでできるのですが、日本語だとWindows 10のファイルエクスプローラで文字化けすることがあります。そんなときもGrooveミュージックやiTunesでは表示されるので、これはTagLibの問題ではなく、タグを解釈するアプリ側の問題です。<br />
<br />
手っ取り早い解決策は、次の例のようにタグのバージョンをID3v2.4にすることです。<br />
<br />
tag = (TagLib.Id3v2.Tag)TagFile.GetTag(TagLib.TagTypes.Id3v2, true);<br />
tag.Version = 4;<br />
<br />
File作成時はMP3ファイルのタグバージョンが適用されるので、読み込み後に変更します。<br />
GetTag()の第二引数にtrueをつけると、Tagがない場合は新規作成します。<br />
<div>
<br /></div>
いささか解せないのは、タグ未設定のMP3にエクスプローラのプロパティーで属性を設定すると、ID3V2.3のタグが設定されることです。ID3V2.3がデフォルトバージョンならちゃんと対応してほしいものですが...<br />
<br />
もうひとつの方法はいったんID3V2.3を全て削除し、必要なタグだけ設定する方法です。これは後述しますが、ID3V2タグを再作成すると非同期化がOFFになるからです。<br />
<br />
TagFile = TagLib.File.Create(filePath);<br />
TagFile.RemoveTags(TagLib.TagTypes.Id3v2);<br />
TagLib.Id3v2.Tag tag =<br />
(TagLib.Id3v2.Tag)TagFile.GetTag(TagLib.TagTypes.Id3v2, true);<br />
<div>
<br /></div>
余分なタグを消してファイルサイズを小さくできるので、場合によっては有用でしょう。<br />
<div>
<br /></div>
これで一件落着なのですが、なぜ文字化けが発生するか調べたので書いておきます。<br />
<br />
冒頭のコードで発生するエクスプローラの文字化けには、次の要因が絡んでいます。</div><div>
①ID3v2タグの非同期化フラグがONになっている。<br />
②項目により文字化ける場合と無効(非表示)となる場合がある。<br />
③ID3V2タグで未設定だがID3V1に対応する項目があると、ID3V1の項目が適用される。<br />
④ID3V2タグが無効だがID3V1に対応する項目があると、変更は無視され、ID3V1の項目が表示される。<br />
<br />
①の非同期化とは、MP3v2タグに対応していなアプリがタグを音声データと誤認しないようにするための処理で、この結果UTF16文字列の先頭BOMが0xFFEE"だと”0xFF00EE"に変換されます。この場合にWindows 10のエクスプローラで文字化けが発生します。試しにバイナリエディタで”0xFFEE00"に変更してみると、文字化けが解消します。</div><div>
<br />冒頭のコードのように tagFile.TagのプロパティーにStringをセットした場合は、ID3V2.3ではUTF16ですが、ID3V2.4ではUTF8で出力されます。そのため、ID3V2.4では”0xFF00EE"は発生しません。<br />
<br />
非同期化フラグはID3V2.4にも存在し、ONの場合に類似の処理が行われます。以下のコードでUTF16で出力すると”0xFF00EE"というバイトシーケンスが発生します。ですが、エクスプローラはID3V2.4は適切に処理してくれるようで、文字化けしません。<br />
<br />
frameの文字コードを設定し、frameのTextにStringをセットします。<br />
<br />
TextInformationFrame fTIT2 =<br />
TextInformationFrame.Get(tag, FrameType.TIT2, StringType.UTF16, true);<br />
fTIT2.TextEncoding = StringType.UTF16;<br />
fTIT2.Text = new String[] { "タイトル” };<br />
<div>
<br /></div>
非同期化をOFFにすれば文字化けしなくなるのですが、MP3ファイルの非同期化フラグはTagLib.Tagクラスのプライベート変数にセットされ、それを操作するパブリックメソッドはありません。<br />
<br />
ただし冒頭に書いたように、いったんID3V2タグを削除し再作成すれば、非同期化がOFFの状態になります。<br />
<br />
TagLibのソースコードを変更すればプログラムでの対応も可能で、例えば次のようにTagLib.Id3v2.Tag.cs にメソッドを追加し、Save()を呼ぶ前にこのメソッドを呼ぶと非同期化をOFFにできます。<br />
<br />
public void ClearUnsynchronisationFlag ()<br />
{<br />
header.Flags &= ~HeaderFlags.Unsynchronisation;<br />
}<br />
<div>
<br />
非同期化はID3V2.3を認識しない再生アプリのための処理なので、そんな古いアプリを考慮する必要がなければ問題ないでしょう。Windows 10のエクスプローラでも、MP3ファイルのタグ情報をプロパティダイアログの詳細で変更、保存すると非同期化はOFFになります。これを利用すればID3V2.3のままでの文字化け対策にもなります。<br />
<br />
項目によって現象が異なり、TitleとAlbumは次の要領でUTF16BEを適用することで文字化けを解消できます。UTF16BEにはBOMがなく”0xFF00EE"が発生しないことが影響しているのでしょう。<br />
<br />
TextInformationFrame fTIT2 = TextInformationFrame.Get(tag2, FrameType.TIT2, StringType.UTF16BE, true);<br />
TextInformationFrame fTALB = TextInformationFrame.Get(tag2, FrameType.TALB, StringType.UTF16BE, true);<br />
fTIT2.TextEncoding = StringType.UTF16BE;<br />
fTALB.TextEncoding = StringType.UTF16BE;<br />
<div>
<div>
fTIT2.Text = new String[] { TitleString };</div>
<div>
fTALB.Text = new String[] { AlbumString };</div>
</div>
<div>
<br /></div>
<div>
既存のFrameがある場合、Getが返すFrameのStringTypeは既存の設定のままなので、StringTypeの再設定を行っています。</div>
<div>
<br /></div>
<div>
残念ながらPerformers(参加アーティスト)はこれでも文字化けます。あまり現実的ではありませんが、Performersは半角英数字(Laten1)に限れば次のコードで文字化け回避できます。</div>
<div>
<br /></div>
<div>
<div>
TextInformationFrame fTPE1 = TextInformationFrame.Get(tag2, FrameType.TPE1, StringType.Latin1, true);</div>
</div>
<div>
<div>
fTPE1.TextEncoding = StringType.Latin1;</div>
</div>
<div>
<div>
fTPE1.Text = new String[] { PerformersString };</div>
</div>
<div>
<br /></div>
<div>
③の現象は、MP3ファイルにまだID3V2タグがない、あるいは対象項目がセットされていない場合に発生します。</div>
<div>
TextInformationFrame.Get(tag2, FrameType.TIT2, StringType.UTF16, true);を使用することでID3V2タグがまだない場合は新規作成してくれます。</div>
<div>
TextInformationFrame.Get(tag2, FrameType.TIT2, StringType.Latin1, true);を使用することで、対象項目がセットされていない場合は追加してくれます。</div>
<div>
<br /></div>
<div>
それでも非同期化がONだと④の現象が発生し、ID3V2への変更は無視され、ID3V1の情報が表示されます。</div>
<div>
<br /></div>
ついでながら、TagLibではUTF16LEも定義されています。TagLibとしては処理しているのですが、UTF16LEではエクスプローラに文字が表示されません。GrooveミュージックでもiTunesでもダメです。調べた範囲では、ID3V2の仕様ではUTF16LEは定義されていないようです。<br />
<br /></div><div>----------</div><div><br /></div><div>【追記】</div><div>既に設定済みのMP3タグをTagLibで読み込むと文字化けしてしまうことがあります。</div><div>次のページに対応策が紹介されています。</div><div><a href="https://resanaplaza.com/2020/06/20/%E7%B7%A8%E9%9B%86%E3%83%84%E3%83%BC%E3%83%AB%E3%81%AE%E8%87%AA%E4%BD%9C%E3%81%A7%E3%82%B9%E3%82%AD%E3%83%AB%E3%82%A2%E3%83%83%E3%83%97%EF%BC%88%E6%9C%80%E7%B5%82%E5%9B%9E%E3%83%BBtaglib%E3%81%AE/">編集ツールの自作でスキルアップ(最終回・TagLibの使い方)</a></div>
</div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-37163420203558965762019-01-07T14:00:00.003+09:002019-12-17T16:37:53.132+09:00Windowsキーを無効にする方法幼児用のお遊びアプリを作ってみたのですが、なにせメチャクチャにキーをたたくので、Windowsキーなどシステムが優先的にイベントを扱うキーが押されるとスタートメニューが表示されたり、Print Scrで画面がキャプチャーされたりしてしまいます。<br />
<br />
そこで、こうしたキーを無効にする方法を調べてみました。<br />
<br />
まずはMicorosoftのページ。<br />
<a href="https://docs.microsoft.com/ja-jp/windows/desktop/DxTechArts/disabling-shortcut-keys-in-games">Disabling Shortcut Keys in Games</a><br />
<br />
ゲームなどで誤って <span style="background-color: white; font-family: "segoe ui" , "segoeui" , "segoe wp" , "helvetica neue" , "helvetica" , "tahoma" , "arial" , sans-serif; font-size: 16px;">Windows key</span><span style="background-color: white; font-family: "segoe ui" , "segoeui" , "segoe wp" , "helvetica neue" , "helvetica" , "tahoma" , "arial" , sans-serif; font-size: 16px;"> を押してしまっても、好ましくない動作をしないようにする方法を紹介しています。しかし、C++なので C# のプロジェクトにはそのままでは導入できません。</span><br />
<br />
こちらからはC#のサンプルがダウンロードできます。<br />
<a href="https://www.codeproject.com/Articles/19004/%2FArticles%2F19004%2FA-Simple-C-Global-Low-Level-Keyboard-Hook">A Simple C# Global Low Level Keyboard Hook</a> (StomySpike / Code Project)<br />
<div>
<br />
そのままソースを取り込んでも動作可能ですが、このソースのままだと次のようなエラーが発生します。<br />
<br />
マネージ デバッグ アシスタント 'CallbackOnCollectedDelegate' が発生しました<br />
…コールバックが、型 '...+keyboardHookProc::Invoke' のガベージ コレクションされたデリゲートで行われました。…デリゲートをアンマネージ コードに渡すとき、デリゲートは 2 度と呼び出されないことが確実になるまでマネージ アプリケーションによって維持されなければなりません。'<br />
<br />
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
これの解決策が次の Stack Overflow のQ&Aにありました。私は、これに従って<span style="font-family: Meiryo;">若干変更して使っています。</span></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<a href="https://stackoverflow.com/questions/6193711/call-has-been-made-on-garbage-collected-delegate-in-c">Call has been made on garbage collected delegate in C#?</a></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<br /></div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
C++のアンマネージドの環境ではdelegateがガベージ コレクションされなかったが、C#のマネージドの環境ではガベージ コレクションされてしまい、その結果上記のエラーが発生します。</div>
<div style="-webkit-text-stroke-width: 0px; color: black; font-family: Meiryo; font-size: medium; font-style: normal; font-variant-caps: normal; font-variant-ligatures: normal; font-weight: 400; letter-spacing: normal; margin: 0px; orphans: 2; text-align: start; text-decoration-color: initial; text-decoration-style: initial; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px;">
<br />
同様の内容のページがあります。</div>
<div style="margin: 0px; text-indent: 0px;">
<span style="font-family: meiryo;"><a href="http://www.cafeole.me/programming/callbackoncollecteddelegate-has-occurred/">CallbackOnCollectedDelegate が発生しました。</a>(Cafe's Room)</span><br />
<span style="font-family: meiryo;"><br /></span>
<span style="font-family: meiryo;">callbackOnCollectedDelegateについての</span><span style="font-family: meiryo;">Microsoftの</span><span style="font-family: meiryo;">解説です。</span><br />
<span style="font-family: meiryo;"><a href="https://docs.microsoft.com/ja-jp/dotnet/framework/debug-trace-profile/callbackoncollecteddelegate-mda">callbackOnCollectedDelegate MDA</a></span><br />
<br /></div>
このソースで使われている関数については、次のページの説明が参考になります。<br />
<span style="font-family: inherit;"><a href="http://eternalwindows.jp/windevelop/message/message07.html">EternalWindows / Windows 開発 / メッセージ管理 / メッセージフック</a></span></div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-51425410083748728392018-12-02T23:40:00.004+09:002022-10-23T11:07:47.454+09:00C# Properties.Settings user.configの破損による例外発生への対応Properties.Settingsを使用したアプリケーション設定を利用していますが、これが保存されるuser.configが何故か壊れ、次の例外が発生するようになりました。<br />
<div>
<br />
System.Configuration.ConfigurationErrorsException<br />
構成システムを初期化できませんでした。<br />
<br /></div>
<div>
たぶんデバッグ中にuser.configが正常に保存されなかったためだと思いますが、この状態になるとなんとも困ったことになります。</div>
<div>
<br /></div>
<div>
user.configはxmlファイルですが、これが破損するとロード時にエラーが発生します。その結果、Properties.Settings.Defaultのプロパティーに適切な値が設定されず、get/setいずれでもエラーが発生するようになってしまいます。</div>
<div>
<br /></div>
<div>
いろいろ試したところでは、Properties.Settings.Defaultオブジェクトは一度だけ作られ、Reloadしても作り直されません。私の結論としては、user.configを削除しアプリを再起動するしか回復の方法がありません。</div>
<div>
<br /></div>
<div>
user.configを削除してアプリを再起動すれば、設定は初期状態になるものの、例外は発生しなくなります。</div>
<div>
<br /></div>
<div>
user.configは通常は次の場所にあるでしょう。<br />
C:\Users\<i>UserName</i>\AppData\Local\<i>AppName</i>\<i>AppName</i>.exe_Url_<i>HashValue</i><br />
<br />
このフォルダの場所はOSバージョンやインストールの仕方で異なる可能性があり、ハッシュ値はアプリのバージョンにより異なること可能性があります。また、開発環境ではビルドによっても異なるハッシュ値が作られることがあります。</div>
<div>
<br /></div>
<div>
この問題への対処方法が次のWebページにありました。</div>
<div>
<div>
<a href="https://www.codeproject.com/Articles/30216/%2FArticles%2F30216%2FHandling-Corrupt-user-config-Settings">Handling Corrupt "user.config" Settings</a></div>
</div>
<div>
<br /></div>
<div>
Properties.Settings.Defaultへのアクセスで例外が発生したときに、そのInnerExceptionのFileNameを使い、user.configを削除しています。</div>
<div>
<br /></div>
<div>
このWebページでは削除後に Settings.Default.Reload(); を呼んでいますが、どうやらReloadはすでに読み込んだxmlから値を元に戻すようで、Settings.Defaultのプロパティーのエラー状態は回復しません。Reloadではうまくいかないことはこのページのコメントにも書かれています。</div>
<div>
<br /></div>
<div>
そこで、次のような要領で、エラーが発生したらuser.configを削除し、アプリを再起動するようにしました。</div>
<div>
<br /></div>
<div>
<div>
try</div>
<div>
{</div>
<div>
<span style="white-space: pre;"> </span>String val = Properties.Settings.Default.<i>someStringProperty</i>;</div>
<div>
}</div>
<div>
catch (Exception ex)</div>
<div>
{<br />
//MessageBox.Show("設定ファイルが破損しています。...");</div>
<div>
<span style="white-space: pre;"> </span>string filePath = ((ConfigurationErrorsException)ex.InnerException).Filename;</div>
<div>
<span style="white-space: pre;"> </span>File.Delete(filePath);</div>
<div>
<span style="white-space: pre;">Application.Restart();</span></div>
<div>
}</div>
<div>
<br /></div>
</div>
<div>
VisualStudioでConfigurationErrorsExceptionが見つからない場合は、プロジェクトの参照にSystem.Co<span>n</span>figurationを追加します。</div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-62388295265973110812018-05-20T15:30:00.007+09:002022-10-03T08:35:53.684+09:00Windowsファイル履歴のエラー<b>Windows ファイル履歴実行されない場合の対処法</b><br />
(同一フォルダ内の<span face=", "meiryo" , "ヒラギノ角ゴ pro w3" , "hiragino kaku gothic pro" , , "yugothic" , "yugothic m" , "ms pゴシック" , "ms pgothic" , sans-serif" style="color: #333333; font-size: 16px;">全角/半角同名のファイルをチェックするJSスクリプト)</span><br />
<br />
しばらく前からWindows 10のファイル履歴が更新されなくなっていました。<br />
イベントログを見るとエラーが発生しています。<br />
<br />
コントロールパネル > ファイル履歴 > 詳細設定 > ファイル履歴イベントログにつぎのエラーが書かれていました。<br />
<br />
<b>C:\Users\<i>(userName)</i>\AppData\Local\Microsoft\Windows\FileHistory\Configuration\Config でユーザー ライブラリの変更のスキャンと変更されたファイルのバックアップを実行できません</b><br />
<br />
<span style="font-family: inherit;">これは、<span face=""arial" , "verdana" , "lucida grande" , "ms pゴシック" , "ヒラギノ角ゴ pro w3" , sans-serif">同じフォルダーに、全角と半角で同じ名前のファイルが保存されていると、正しくバックアップできないために発生するとのこと。</span></span><br /><br />
<div>
マイクロソフト コミュニテー</div>
<span face=""arial" , "verdana" , "lucida grande" , , "pro w3" , sans-serif"><a href="https://answers.microsoft.com/ja-jp/windows/forum/windows8_1-update/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%B1%A5/9a3a41cd-ba5d-492e-8cf6-0593c8892213?auth=1">ファイル履歴が動作しない </a></span><br />
<div>
<div>
<br /></div>
</div>
<span style="font-family: inherit;"><span face=""arial" , "verdana" , "lucida grande" , "ms pゴシック" , "ヒラギノ角ゴ pro w3" , sans-serif"></span></span>
富士通Q&A<br />
<a href="https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=8610-8544"><span id="goog_1700258256"></span>[Windows 10] ファイル履歴で正しくバックアップされているかどうかを確認する方法を教えてください。</a><br />
<span face=""arial" , "verdana" , "lucida grande" , , "pro w3" , sans-serif"><br class="Apple-interchange-newline" />私の場合にも</span>確かに<span face=""arial" , "verdana" , "lucida grande" , , "pro w3" , sans-serif">上記のファイル名に該当するものがありましたが、それを直してもまだエラーが発生しました。</span>そこで次の方法を試したところ回復しました。ライブラリに含まれるドキュメントなどの場所を変更したりしていたので、何かConfigがおかしくなったのかもしれません。<br />
<ul>
<li>次のフォルダを削除(リネームし成功したら削除する方が安全)<br />C:\Users\<i>(userName)</i>\AppData\Local\Microsoft\Windows\FileHistory</li>
<li>コントロールパネル > ファイル履歴でドライブ選択し「今すぐ実行」</li>
</ul>
<span id="goog_1700258257"></span>問題となるファイルを探すのに目視で調べるのは厄介なので、javascriptでファイル名のダブりをチェックするスクリプトを作ってみました。このスクリプトで”要チェック”と表示されるファイル/フォルダ名を調べてみてください。エラーにならない場合もどちらか一方しかファイル履歴に保存されていない可能性がありますので、チェックしてみる価値はあるでしょう。<div><br /></div><div>
このブログの後半にソースを載せてあります。</div><div><br />
このスクリプトには<span face=""arial" , "verdana" , "lucida grande" , "ms pゴシック" , "ヒラギノ角ゴ pro w3" , sans-serif">全角/半角文字の対象リストがあります。私の場合はこれで問題になっていたファイルが見つけられましたが、このリストに問題になる文字が全て含まれているかわかりません。また、この</span>スクリプトで”要チェック”とされても、実際には問題ない場合もあるでしょう。<br />
<br />
状況はいささか複雑で、ファイル履歴が更新されるがいずれか一方しか履歴に保存されない場合もあり、またファイル履歴に保存・更新される順序でエラーになったりならなかったりすることもあるようです(手間がかかるので十分調べていません)。<br />
また、フォルダ名とファイル名の間でも同様のことが発生します。<br />
<div>
<br /></div>
以下は次の環境で試した結果です。Windowsのバージョンによって動作が異なるかもしれません。</div><div><br />
テスト環境:Window 10 Pro, バージョン 1709, OS ビルド 26299.431<br />
<ul>
<li>エラーが発生する例:<br />space .txt <=> space .txt (全角/半角スペース)<br />space ].txt <=> space ].txt (全角/半角スペース)<br />TEST1.txt <=> TEST1.txt (全角/半角数字)<br />test <=> TEST (半角フォルダ名と全角ファイル名) </li>
</ul>
<ul>
<li>エラーは発生しないがどちらか一方しか履歴に残らない例:<br />space[ ].txt <=> space[ ].txt (全角/半角スペース)<br />TEST.TXT <=> test.txt (全角/半角アルファベット、ピリオドいずれも半角)<br />test# <=> TEST# (半角フォルダ名と全角ファイル名)</li>
</ul>
なぜこんなことが起こるか考えてみました。<br />
<br />ポイントは、エラーは発生しないがどちらか一方しか履歴に残らない場合がある、ということでしょう。エクスプローラにとっては別ファイルだが、ファイル履歴にとっては同一ファイルとみなされる場合あるということです。</div><div><br />
まずはWindowsのファイル名ではアルファベットの大文字小文字は区別されません。TEST.TXTとtest.txtは同じフォルダ内では同一ファイルとなり、そもそも別々に保存できません。これはファイル履歴でも同じです。<br />
<br />
ファイルエクスプローラでのファイル名順のソートはSQLサーバの照合順序(WI)に準じているようで、全角/半角で同一文字とみなされるものは同等に扱われます。全角Aと半角Aは同等ですがイコールではなく、いずれも全角B、半角Bより小さいが、全角Aは半角Aより大きいと判断され、全角/半角はファイル名としては別のものとして扱われます。TEST.TXTとTEST.TXTは別ファイルになります。ところが、ファイル履歴ではどちらか一方しか保存されません。つまり同一ファイル(イコール)とみなされます。</div><div>
<br />
ファイル履歴ではファイルエクスプローラの照合順序で同等のファイル名は同一ファイルとして扱われているような感じです。照合順序の判定では最初に同一文字として扱う文字を半角大文字に統一するなどして大小比較するでしょう。ここでイコールの場合に、ファイルエクスプローラでは元の名前で比較し大小を決定しているようですが、ファイル履歴では同一ファイルとして扱っているのではないかと思います。どういう場合にエラーになるかはわかりませんが、異なるファイルを同一ファイルとして扱おうとするのだから、エラーが発生しても不思議ではありません。<br />
<br />
理由はともあれ、あやしそうなファイルはリネームしておいた方が無難でしょう。<br /><ul>
</ul>
------------------- スクリプト -------------------<br />
<br />
//以下のスクリプトをテキストファイルにコピーし、<br />
//fileNameCheck.jsなどの拡張子.jsの名前で保存する。<br />
<br />
//コマンドプロンプト(cmd.exe)で、CScriptで実行する。<br />
//例: >CScript fileNameCheck.js<br />
<br />
//WScriptだとEchoの度にダイアログが表示される。<br />
<br />
//ファイル履歴の対象フォルダをプログラムで取得する方法がわからないので、<br />
//チェックするフォルダのリストを各自の環境に合わせて設定する。<br />
var homeDir = "C:\\Users\\UserName\\";<br />
var folderPaths = [<br />
homeDir + "Desktop",<br />
homeDir + "Documents",<br />
homeDir + "Pictures",<br />
homeDir + "Videos",<br />
homeDir + "Music"<br />
];<br />
<br />
//半角と同じと判断される文字の全角、半角対照辞書。<br />
//regularizeNameでzen2hanに含まれる全角文字が見つかった場合、半角文字に置き換える。<br />
//'#'などの記号は問題ないかもしれない。<br />
//また、ハイフン、ピリオドなどは対応する全角文字が複数あるため、適切な対応は不明。<br />
var zen2han = {<br />
' ': ' ',<br />
'a': 'a',<br />
'b': 'b',<br />
'c': 'c',<br />
'd': 'd',<br />
'e': 'e',<br />
'f': 'f',<br />
'g': 'g',<br />
'h': 'h',<br />
'i': 'i',<br />
'j': 'j',<br />
'k': 'k',<br />
'l': 'l',<br />
'm': 'm',<br />
'n': 'n',<br />
'o': 'o',<br />
'p': 'p',<br />
'q': 'q',<br />
'r': 'r',<br />
's': 's',<br />
't': 't',<br />
'u': 'u',<br />
'v': 'v',<br />
'w': 'w',<br />
'x': 'x',<br />
'y': 'y',<br />
'z': 'z',<br />
'A': 'a',<br />
'B': 'b',<br />
'C': 'c',<br />
'D': 'd',<br />
'E': 'e',<br />
'F': 'f',<br />
'G': 'g',<br />
'H': 'h',<br />
'I': 'i',<br />
'J': 'j',<br />
'K': 'k',<br />
'L': 'l',<br />
'M': 'm',<br />
'N': 'n',<br />
'O': 'o',<br />
'P': 'p',<br />
'Q': 'q',<br />
'R': 'r',<br />
'S': 's',<br />
'T': 't',<br />
'U': 'u',<br />
'V': 'v',<br />
'W': 'w',<br />
'X': 'x',<br />
'Y': 'y',<br />
'Z': 'z',<br />
'1': '1',<br />
'2': '2',<br />
'3': '3',<br />
'4': '4',<br />
'5': '5',<br />
'6': '6',<br />
'7': '7',<br />
'8': '8',<br />
'9': '9',<br />
'0': '0',<br />
'@': '@',<br />
'!': '!',<br />
'"': '"',<br />
'#': '#',<br />
'$': '$',<br />
'%': '%',<br />
'&': '&',<br />
'\': '\'',<br />
'(': '(',<br />
')': ')',<br />
'=': '=',<br />
'-': '-',<br />
'~': '~',<br />
'^': '^',<br />
'|': '|',<br />
'\': '\\',<br />
'[': '[',<br />
';': ';',<br />
':': ':',<br />
']': ']',<br />
',': ',',<br />
'.': '.',<br />
'/': '/',<br />
'`': '`',<br />
'{': '{',<br />
'+': '+',<br />
'*': '*',<br />
'}': '}',<br />
'<': '<',<br />
'>': '>',<br />
'?': '?',<br />
'_': '_'<br />
};<br />
<br />
var fso = new ActiveXObject('Scripting.FileSystemObject');<br />
//zenに含まれる文字が対象文字列にあるか判断するのに用いる正規表現。初期化時にセットする。<br />
var regexZen;<br />
<br />
//.jsファイルをダブルクリックするとWScriptで実行されるので、exeの名前をチェックし、WScriptの場合は警告を出して終了する。<br />
if (/cscript\.exe$/i.test(WScript.FullName)) {<br />
//zenに含まれる文字が対象文字列にあるか判断するのに用いる正規表現をセットする。<br />
var str = "[";<br />
for (key in zen2han) {<br />
str += key;<br />
}<br />
str += "]";<br />
regexZen = new RegExp(str);<br />
//対象のフォルダを順次チェックする。<br />
for (var i = 0; i < folderPaths.length; i++) {<br />
var folderPath = folderPaths[i];<br />
if (fso.FolderExists(folderPath)) {<br />
folderCheck(fso.GetFolder(folderPath));<br />
} else {<br />
WScript.Echo("Folderなし: " + folderPath);<br />
}<br />
}<br />
} else {<br />
WScript.Echo("CScriptで実行してください。")<br />
}<br />
<br />
function folderCheck(folder) {<br />
//動作確認時にコメントを外すとチェック中のフォルダ名をログ表示する。<br />
//WScript.Echo("FOLDER: " + folder.Path);<br />
<br />
//フォルダ毎に辞書を初期化。<br />
var nameDict = [];<br />
//フォルダ内のファイル名をチェック。<br />
<span style="white-space: pre;"> </span>var files = new Enumerator(folder.Files);<br />
for (; !files.atEnd(); files.moveNext()) {<br />
var file = files.item();<br />
regularizeName(file, nameDict);<br />
}<br />
//サブフォルダの名前をチェックし、再帰的にfolderCheckを実行。<br />
<span style="white-space: pre;"> </span>var subFolders = new Enumerator(folder.SubFolders);<br />
for (; !subFolders.atEnd(); subFolders.moveNext()) {<br />
var subFolder = subFolders.item();<br />
regularizeName(subFolder, nameDict);<br />
<span style="white-space: pre;"> </span>folderCheck(subFolder);<br />
<span style="white-space: pre;"> </span>}<br />
}<br />
<br />
//zenに含まれる文字がある場合、それに対応するhanの文字に置き換える。<br />
function regularizeName(item, nameDict) {<br />
var name = item.Name, newName;<br />
if (regexZen.test(name)) {<br />
//zen2hanに含まれる全角文字が見つかった場合、対応する半角に置き換え。<br />
var chars = name.split('');<br />
for (var n = 0; n < chars.length; n++) {<br />
var han = zen2han[chars[n]];<br />
if (han) {<br />
chars[n] = han;<br />
}<br />
}<br />
newName = chars.join('').toLowerCase();<br />
} else {<br />
//zen2hanに含まれる全角文字がない場合は小文字に統一。<br />
newName = name.toLowerCase();<br />
}<br />
var registerdItem = nameDict[newName];<br />
if (registerdItem) {<br />
//zen2hanで全角を半角に変換した名前が既に登録済みの場合にログを出力。<br />
WScript.Echo("要チェック:" + item.Path + " <=> " + registerdItem.Name);<br />
} else {<br />
//まだnameDictに登録されていない場合は追加。<br />
nameDict[newName] = item;<br />
}<br />
}<br />
<div>
<br /></div>
<ul style="font-family: Arial, Verdana, "Lucida Grande", "MS Pゴシック", "ヒラギノ角ゴ Pro W3", sans-serif; font-size: 15.444px; line-height: 23.166px; margin-bottom: 1.75em; margin-left: 0px; margin-top: 0px; padding: 0px 0px 0px 2.8em;"></ul>
</div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-55210130933640705302017-11-15T15:07:00.001+09:002017-11-25T18:58:20.704+09:00WiX toolset msi ダイアログ多国語対応 <a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html">以前のブログ</a>でWiX toolsetによる多国語対応msiの作り方について書いたが、インストーラの主要なメッセージの表示が日本語化されても、細かなダイアログのメッセージが英語のままであった。<br />
<br />
WiX tooksetの以下の場所に多国語メッセージ定義ファイルがある。<br />
C:\Program Files (x86)\WiX Toolset v3.11\SDK\wixui<br />
<br />
これに含まれる <a href="https://github.com/AnalogJ/Wix3.6Toolset/blob/master/RC0-source/wix36-sources/src/ext/UIExtension/wixlib/WixUI_ja-jp.wxl">WixUI_ja-jp.wxl</a> で日本語メッセージが設定されているが、これが適用されない項目がある。<br />
<div>
</div>
<br />
ここに同様の件でのQ&Aがあった。<br />
<a href="https://stackoverflow.com/questions/5973994/wix-statuses-while-rolling-back-uninstall-are-not-localized-in-french/15530630#15530630" style="background-color: white; font-family: arial, helvetica, sans-serif;">WIX: Statuses while rolling back uninstall are not localized in French</a><br />
<br />
これによるとActionに対応するローカライズテキストがデフォルトでは設定されていないようで、Product.wxsに次のような追加を行うと、日本語メッセージが適用されるようになる。<br />
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">この Q&A では String の Id を別のものに置き換え、言語別 wxl でメッセージを書き換えているが、WiX規定のものであれば次の要領で日本語を適用できる。</span><br />
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br />
</span></div>
<div>
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"> <UI>
<ProgressText Action="RemoveShortcuts" Template="!(loc.ProgressTextRemoveShortcutsTemplate)">
!(loc.ProgressTextRemoveShortcuts)
</ProgressText>
</UI></span>
</pre>
</div>
<div>
<br />
<pre></pre>
</div>
<div>
これにより Action="<span style="font-family: "arial" , "helvetica" , sans-serif;">RemoveShortcuts” に ja-JP では </span><span style="font-family: "arial" , "helvetica" , sans-serif;">WixUI_ja-jp.wxl の </span><span style="font-family: "arial" , "helvetica" , sans-serif;">ProgressTextRemoveShortcuts が適用されるようになる。</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br />
</span> <span style="font-family: "arial" , "helvetica" , sans-serif;"> </span><span style="font-family: "arial" , "helvetica" , sans-serif;">WixUI_ja-jp.wxl では次のように設定されている。</span><br />
<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><String Id="ProgressTextRemoveShortcuts" Overridable="yes">ショートカットを削除しています</String>
<String Id="ProgressTextRemoveShortcutsTemplate" Overridable="yes">ショートカット: [1]</String></span>
</pre>
<br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">ProgressText の Template がなくてもエラーにはならないが、メッセージが表示されなくなるかもしれないので設定しておいたほうがよいだろう。ただし、メッセージによっては </span><span style="font-family: "arial" , "helvetica" , sans-serif;">Template が設定されいないものがあり、その場合は </span><span style="font-family: "arial" , "helvetica" , sans-serif;">Template は不要で、設定したが対応するStringがないとエラーになる。</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br />
</span> <span style="font-family: "arial" , "helvetica" , sans-serif;">Actionに対応するものは以上で置き換わるが、これだけでは日本語化されないものもある。</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;">たとえば、”</span><span style="font-family: "arial" , "helvetica" , sans-serif;">Please wait while Windows configures <i>MyApp</i>"があるが、これはWiX toolset で次のように設定されている。<br />
</span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br />
</span> <br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://www.blogger.com/blogger.g?blogID=6538117324271148932#editor/target=post;postID=5521013093364070530;onPublishedMenu=allposts;onClosedMenu=allposts;postNum=0;src=postname">ErrorProgressText.wxs</a>
<Error Id="20">!(loc.Error20)</Error>
WixUI_en-us.wxl
<String Id="Error20" Overridable="yes">Please wait while Windows configures [ProductName]</String>
</span></pre>
<br />
このようなものについては Product.wxsの UI タグに次のように設定を追加する。<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;">
</span></pre>
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"> <UI>
<Error Id="20">!(loc.Error20)</Error>
</UI></span></pre>
<br />
以下 UI タグの設定例。気付いたところだけ対応したもの。また、Actionについては上記Q&Aに含まれていたものを入れてあるので、msiによっては不要なものもある。<br />
<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><UI>
<ProgressText Action="FileCost">!(loc.ProgressTextFileCost)</ProgressText>
<ProgressText Action="InstallFiles" Template="!(loc.ProgressTextInstallFilesTemplate)">!(loc.ProgressTextInstallFiles)</ProgressText>
<ProgressText Action="CreateShortcuts" Template="!(loc.ProgressTextCreateShortcutsTemplate)">!(loc.ProgressTextCreateShortcuts)</ProgressText>
<ProgressText Action="WriteRegistryValues" Template="!(loc.ProgressTextWriteRegistryValuesTemplate)">!(loc.ProgressTextWriteRegistryValues)</ProgressText>
<ProgressText Action="RegisterUser" Template="!(loc.ProgressTextRegisterUserTemplate)">!(loc.ProgressTextRegisterUser)</ProgressText>
<ProgressText Action="RegisterProduct" Template="!(loc.ProgressTextRegisterProductTemplate)">!(loc.ProgressTextRegisterProduct)</ProgressText>
<ProgressText Action="PublishFeatures" Template="!(loc.ProgressTextPublishFeaturesTemplate)">!(loc.ProgressTextPublishFeatures)</ProgressText>
<ProgressText Action="PublishProduct">!(loc.ProgressTextPublishProduct)</ProgressText>
<ProgressText Action="RemoveFiles" Template="!(loc.ProgressTextRemoveFilesTemplate)">!(loc.ProgressTextRemoveFiles)</ProgressText>
<ProgressText Action="RemoveExistingProducts" Template="!(loc.ProgressTextRemoveExistingProductsTemplate)">!(loc.ProgressTextRemoveExistingProducts)</ProgressText>
<ProgressText Action="RemoveShortcuts" Template="!(loc.ProgressTextRemoveShortcutsTemplate)">!(loc.ProgressTextRemoveShortcuts)</ProgressText>
<ProgressText Action="Rollback" Template="!(loc.ProgressTextRollbackTemplate)">!(loc.ProgressTextRollback)</ProgressText>
<ProgressText Action="RollbackCleanup" Template="!(loc.ProgressTextRollbackCleanupTemplate)">!(loc.ProgressTextRollbackCleanup)</ProgressText>
<Error Id="16">!(loc.Error16)</Error>
<Error Id="20">!(loc.Error20)</Error>
<Error Id="21">!(loc.Error21)</Error>
</UI></span></pre>
<br />
でも、これって ErrorProgressText.wxs の一部ですね。ということで、ErrorProgressText.wxs の UI タグの中身をすっかり Product.wxs にコピーしてみた。特に問題はなさそうだ。違いはというと ErrorProgressText.wxs は wixlib のビルド時に適用され、Product.wxs はmsiビルド時に適用されているということだと思う。<br />
<br /></div>
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><div style="font-family: Meiryo; white-space: normal;">
<b>関連ブログ</b></div>
<div style="font-family: Meiryo; white-space: normal;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html">VisualStudio 2017 Community & WiX tools & WiX Edit によるWindowsアプリ インストーラ(msi)作成</a></span></div>
<div style="font-family: Meiryo; white-space: normal;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/dotnetinstallerbootstarpper.html">dotNetInstallerによるシンプルBootstarpper作成</a></span></div>
<div style="font-family: Meiryo; white-space: normal;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper.html">WiX toolsetのBootstarpperを試してみた(1)</a></span></div>
<div style="font-family: Meiryo; white-space: normal;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_10.html">WiX toolsetのBootstarpperを試してみた(2)Detect追加</a></span></div>
<div style="font-family: Meiryo; white-space: normal;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_46.html">WiX toolsetのBootstarpperを試してみた(3)msiexecパラメータ設定</a></span></div>
<div style="font-family: Meiryo; white-space: normal;">
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpperui.html" style="font-family: Arial, Helvetica, sans-serif;">WiX toolsetのBootstarpperを試してみた(4)UI追加</a></div>
</span></pre>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-15774428207946128762017-11-12T14:58:00.000+09:002017-11-24T22:56:44.174+09:00WiX toolsetのBootstarpperを試してみた(4)UI追加さて、前回まででmsi側のUIを使うBootstapperが一応できたが、アンインストール時になにも表示せずに実行、終了してしまうので、UIの追加を行ってみる。<br />
<br />
次のようなコードで、OnDetectPackageCompleteで実行/キャンセルの確認ダイアログを表示し、OnApplyCompleteで終了メッセージが表示される。<br />
<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;">参照に System.WIndows.Forms を追加。</span><span style="font-family: "arial" , "helvetica" , sans-serif;">
</span><span style="font-family: "arial" , "helvetica" , sans-serif;">using System.Windows.Forms;
private void OnDetectPackageComplete(object sender, DetectPackageCompleteEventArgs e)
{
if (e.PackageId == "MyAppSetup.msi")
{
if (e.State == PackageState.Absent)
{
Engine.Plan(LaunchAction.Install);
}
else if (e.State == PackageState.Present)
{
DialogResult res = MessageBox.Show("MyAppSetup",
"アンインストールを実行しますか?", MessageBoxButtons.OKCancel);
if (res == DialogResult.Cancel)
{
Engine.Quit(0);
}
else
{
Engine.Plan(LaunchAction.Uninstall);
}
}
}
}
</span><span style="font-family: "arial" , "helvetica" , sans-serif;">private void OnApplyComplete(object sender, ApplyCompleteEventArgs e)
{
if (IsUninstall)
{
MessageBox.Show(ClassLibrary1.Properties.Resources.UnistallDone);
}
</span></span><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"> </span><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">Engine.Quit(0);</span></span>
</span><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;">}</span><span style="font-family: "arial" , "helvetica" , sans-serif;">
</span><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">
</span></span></pre>
せっかくmsiを多国語化したのに、Bootstarpperが未対応になってしまった。しかし、BootstarpperはC#のクラスライブラリなので、プロジェクトのProperties に String の Resouces.resx を追加することで多国語対応できる。<br />
<br />
msiと同様、ベースを英語とし日本語のResources.ja.resxを追加した場合は次のようにBundle.wxs の BootstrapperApplicationRef にresources.dllを追加する。<br />
<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><BootstrapperApplicationRef Id='ManagedBootstrapperApplicationHost'>
<Payload SourceFile="..\ClassLibrary1\bin\Release\ClassLibrary1.dll" />
<Payload SourceFile="..\ClassLibrary1\bin\Release\ja\ClassLibrary1.resources.dll"
<b>Name="ja\ClassLibrary1.resources.dll"</b> />
<Payload SourceFile="BootstrapperCore.config" />
</BootstrapperApplicationRef></span>
</pre>
<br />
Name属性で ja サブフォルダを追加している。Name属性は展開先のパスで、デフォルト値はファイル名であるため、これがないと同じフォルダにファイルがフラットに展開され、resources.dllがロードされずベース言語のみとなる。<br />
<br />
ここまでで、Cultureに従ってパラメータを切り替えて多国語化した msi を起動するBootstrapper作るという目的は一応実現した。しかし、これだけのためならdotNetInstallerを使ったBootstrapperのほうが目的に適っている。BurnをするならUIをBootstrapperに移し、msiはサイレントで実行した方がよい。<br />
<br />
上記の方法ではインストール実行中、常時ウインドウを表示しておくことはできない。Runは独立したスレッドで呼ばれ、Runからリターンするとスレッドも終了し、ここで表示したFormも消えるか、下手をするとゾンビで残る。また Engine.Quit(0) を呼ぶとプロセスが終了しUIも終了してしまうので、UIが終了してから Engine.Quit(0) を呼ぶ必要がある。<br />
<div>
<br /></div>
<div>
そのためにはUI用のイベントループを作ればよい。ここではFormアプリによる実装例を紹介しておく。</div>
<br />
Run メソッドで Detect を呼んだあと、Application によるループを開始する。<br />
このループ終了後、Engine.Quit(0) を呼ぶ。<br />
BootstapperとFormで相互に互いのインスタンスの参照を持ち、適宜メソッド呼び出し、変数設定などを行う。<br />
<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;">/クラスライブラリにForm1を追加
<b>private Form1 form;</b>
protected override void Run()
{
this.DetectPackageComplete += this.OnDetectPackageComplete;
this.PlanComplete += this.OnPlanComplete;
this.ApplyComplete += this.OnApplyComplete;
<b>this.ExecuteProgress += this.OnExecuteProgress;</b>
if (CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "ja")
{
Engine.StringVariables["TRANSFORMS"] = ":ja-JP.mst";
}
else
{
Engine.StringVariables["TRANSFORMS"] = "";
}
Engine.Detect();
<b> Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
form = new Form1();
form.Bootstrapper = this;
Application.Run(form);</b>
//formがクローズされると Application.Run が終了し、ここにくる。
this.Engine.Quit(0);
}</span>
</pre>
<br />
また、ExecuteProgressイベントで進行状態が通知される。ここでFormに通知を転送することができ、また ExecuteProgressEventArgs にResult.Cancelをセットするとインストールを中断することができる。<br />
<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;">private void OnExecuteProgress(object sender, ExecuteProgressEventArgs e)
{
if ( someEroorCoccured )
{
e.Result = Result.Cancel;
}
else
{
form.SetProgress(e.OverallPercentage.ToString());
}
}</span>
</pre>
<br />
<b>関連ブログ</b><br />
<a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html"><span style="font-family: "arial" , "helvetica" , sans-serif;">VisualStudio 2017 Community & WiX tools & WiX Edit によるWindowsアプリ インストーラ(msi)作成</span></a><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolset-msi.html"><span style="font-family: "arial" , "helvetica" , sans-serif;">WiX toolset msi ダイアログ多国語対応</span></a><br />
<a href="https://ken-plus.blogspot.jp/2017/11/dotnetinstallerbootstarpper.html"><span style="font-family: "arial" , "helvetica" , sans-serif;">dotNetInstallerによるシンプルBootstarpper作成</span></a><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper.html"><span style="font-family: "arial" , "helvetica" , sans-serif;">WiX toolsetのBootstarpperを試してみた(1)</span></a><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_10.html"><span style="font-family: "arial" , "helvetica" , sans-serif;">WiX toolsetのBootstarpperを試してみた(2)Detect追加</span></a><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_46.html">WiX toolsetのBootstarpperを試してみた(3)msiexecパラメータ設定</a></span>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-70549710296229035352017-11-10T14:34:00.003+09:002017-11-15T15:10:44.949+09:00WiX toolsetのBootstarpperを試してみた(3)msiexecパラメータ設定<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_10.html">前回</a>で Bundle から msi の UI を使ってのインストール/アンインストールができるようになった。今回は Bundle のブートストラッパ―で設定したパラメータを用いて msi を起動し、msi側で言語切り替えを行うようにする。<br />
<ul>
<li><b>Bundle の子要素にVariablesタグ追加</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><Bundle ...>
</span><span style="font-family: "arial" , "helvetica" , sans-serif;"><Variable Name="TRANSFORMS"
Value=":ja-JP.mst" Type="string" bal:Overridable="yes"/></span></pre>
</li>
<ul>
<li>Bundleエンジンに変数を追加する。<br />
Name:変数名。<br />
Value:初期値。この例では必ずBootstarpperで設定するので、Valueは別の値でもよい。</li>
<li>bal:Overridable="yes": Bootstarpperで変更できるように"yes"に設定する。</li>
<ul>
<li>bal namespace が認識されない場合はWixタグに次のxmlnsを追加<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;">xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"
</span>
</pre>
</li>
</ul>
</ul>
<li><b>MsiPackage 要素変更</b></li>
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;"><Chain>
<MsiPackage ....>
<MsiProperty Name="TRANSFORMS" Value="[TRANSFORMS]" />
</MsiPackage>
</Chain>
</span></pre>
<ul>
<li><pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif;">Name:msi 作成プロジェクトの Product.wxsのPropertyタグのIdと同じ名前。
msiexecの起動パラメータとして使われる。</span><pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><Property Id="TRANSFORMS" Value="Default" /></span><span style="font-family: "arial" , "helvetica" , sans-serif;">
</span></pre>
</span></pre>
</li>
<li><pre><span style="font-family: "arial" , "helvetica" , sans-serif;">Value="[TRANSFORMS]":BundleのVariableのTRANSFORMSの値で置換される。
</span></pre>
</li>
</ul>
<li><b>MyBootstrapper.csのRunメソッド変更</b><br />
次のようなコードで Variable TRANSFORMS の値をセットする。<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: x-small;">if (CultureInfo.CurrentUICulture.TwoLetterISOLanguageName == "ja")
{
this.Engine.StringVariables["TRANSFORMS"] = ":ja-JP.mst";
}
else
{
this.Engine.StringVariables["TRANSFORMS"] = "";
}</span>
</span></pre>
</li>
<li><b>MySetup.exe実行</b>これらの設定、コードの変更後、MySetup.exeを実行するとMyAppSetup.mstを起動するmsiexecのパラメータに<br />
TRANSFORMS=":ja-JP.mst"、またはTRANSFORMS=""が追加される。</li>
<li><b>ログ出力</b><br />
Bundleのログに、次のように書き出される<span style="font-family: "arial" , "helvetica" , sans-serif; white-space: pre;">。</span></li>
<ul>
<li><b>Installの場合:</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">Applying execute package: MySetup.msi, action: Install,
path: C:\Users\<i style="white-space: pre;">UserName</i><span style="white-space: pre;">\AppData\Local\Package Cache\{</span><i style="white-space: pre;">GUID</i><span style="white-space: pre;">}v1.0.1\MyAppSetup.msi,
arguments: ' ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="7"
TRANSFORMS=":ja-JP.mst"
</span></span></pre>
</li>
<li><b>Uninstallの場合:</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">Applying execute package: MySetup.msi, action: Uninstall,
path: (null),
arguments: ' ARPSYSTEMCOMPONENT="1" MSIFASTINSTALL="7"
TRANSFORMS=":ja-JP.mst"
</span></pre>
</li>
<li><pre><span style="font-family: "arial" , "helvetica" , sans-serif;">Valueが空文字の場合は TRANSFORMS="" となる。</span></pre>
</li>
</ul>
</ul>
これでmsiのUIを使ったインストールは実現できたが、アンインストールはサイレントで実行される。<br />
<br />
TRANSFORMSと同様にmsiexecのパラメータ UILevel、CLIENTUILEVEL を設定してみたが、Bundleが CLIENTUILEVEL=3 (サイレント)をその後ろに付けるため有効にならない。アンインストール実行確認ダイアログや、アンインストール完了時のメッセージ表示などのUIはBootstarpperで用意する必要がある。<br />
<ul>
<li><b>アンインストール時のmsiexecのログ</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-size: x-small;">ARPSYSTEMCOMPONENT=1 MSIFASTINSTALL=7 TRANSFORMS=:ja-JP.mst
<i> <b>UILevel=5 CLIENTUILEVEL=5</b></i><b> </b>REBOOT=ReallySuppress IGNOREDEPENDENCIES=ALL
REMOVE=ALL CURRENTDIRECTORY=C:\WINDOWS\system32
<b>CLIENTUILEVEL=3</b> MSICLIENTUSESEXTERNALUI=1 CLIENTPROCESSID=6296
</span>
</span></pre>
</li>
<ul>
<li><i>UILevel=5 CLIENTUILEVEL=5 は</i>MsiPropertyで設定したもの。burnが設定する<span style="font-family: "arial" , "helvetica" , sans-serif;">CLIENTUILEVEL=3が有効になる。</span></li>
</ul>
</ul>
<b>関連ブログ</b><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html">VisualStudio 2017 Community & WiX tools & WiX Edit によるWindowsアプリ インストーラ(msi)作成</a></span><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolset-msi.html">WiX toolset msi ダイアログ多国語対応</a><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/dotnetinstallerbootstarpper.html">dotNetInstallerによるシンプルBootstarpper作成</a></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper.html">WiX toolsetのBootstarpperを試してみた(1)</a></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_10.html">WiX toolsetのBootstarpperを試してみた(2)Detect追加</a></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpperui.html">WiX toolsetのBootstarpperを試してみた(4)UI追加</a></span><br />
<ul>
</ul>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-74089333881816249042017-11-10T11:25:00.001+09:002017-11-24T22:49:01.399+09:00WiX toolsetのBootstarpperを試してみた(2)Detect追加<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper.html">前回は</a>PlanCompleteとApplyComplete のイベントハンドラ だけを追加したクラスからインストールを開始し、msiのUIによるインストール/アンインストールを行うところまで設定した。<br />
<br />
今回は DetectPackageComplete を追加する。<br />
<ul>
<li><b>Runメソッド変更</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">protected override void Run()
{
this.DetectPackageComplete += this.OnDetectPackageComplete;
this.PlanComplete += this.OnPlanComplete;
this.ApplyComplete += this.OnApplyComplete;
Engine.Detect();
}</span>
</pre>
</li>
<li><b>DetectPackageComplete イベントハンドラ追加</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;"><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">private void OnDetectPackageComplete(object sender, DetectPackageCompleteEventArgs e)
{
if (e.PackageId == "MySetup.msi")
{
if (e.State == PackageState.Absent)
{
Engine.Plan(LaunchAction.Install);
}
else if (e.State == PackageState.Present)
{
Engine.Plan(LaunchAction.Uninstall);
}
</span> }
}</span>
</pre>
</li>
</ul>
前回は Runメソッドで Engine.Plan を呼んでいたが、これを Engine.Detect に変更。その結果、MySetup.msi が見つからなければ Install、見つかれば Unistall を実行するようになる。<br />
<div>
<br /></div>
<div>
これにより MySetup.exe を複数回起動すると、Install と Unistall が交互に繰り返されるようになる。</div>
<div>
<br /></div>
<div>
このとき、次のようなログが書かれる。</div>
<div>
<span style="font-family: "arial" , "helvetica" , sans-serif;">Detected package: MySetup.msi, state: Absent, cached: None</span></div>
<div>
または</div>
<div>
Detected package: MySetup.msi, state: Present, cached: Complete</div>
<div>
<br /></div>
<div>
何度実行しても常に Absent の場合は msi 作成時の ID 設定をチェックする。これが"*"の場合は Present にならない。"*"を固定の GUID に変更する。</div>
<div>
<br /></div>
<div>
Engine.Detect では他に次のイベント呼び出しがあるが、詳しく調べていない。</div>
<div>
<div>
<ul>
<li>DetectRelatedMsiPackage</li>
<li>DetectRelatedBundle</li>
<li>DetectComplete</li>
</ul>
</div>
<div>
次回で Bootstapper で msi 起動時のパラメータを設定し、言語切り替えを行えるようにする。</div>
<div>
<br />
<b>関連ブログ</b><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html">VisualStudio 2017 Community & WiX tools & WiX Edit によるWindowsアプリ インストーラ(msi)作成</a></span><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolset-msi.html">WiX toolset msi ダイアログ多国語対応</a><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/dotnetinstallerbootstarpper.html">dotNetInstallerによるシンプルBootstarpper作成</a></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper.html">WiX toolsetのBootstarpperを試してみた(1)</a></span><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_46.html" style="font-family: Arial, Helvetica, sans-serif;">WiX toolsetのBootstarpperを試してみた(3)msiexecパラメータ設定</a><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpperui.html" style="font-family: Arial, Helvetica, sans-serif;">WiX toolsetのBootstarpperを試してみた(4)UI追加</a><br />
<br /></div>
<b>参考リンク</b><br />
<a href="http://wixtoolset.org/documentation/manual/v3/bundle/ba/bootstrapper_application_interface.html">Bootstrapper Application Interface</a><br />
IBootstrapperApplicationの説明。ソースを見ていないが、ManagedBootstrapperApplicationHost はこれを実装し、C#の BootstrapperApplication のイベント呼び出しを行うものでしょう。<br />
<br />
<a href="https://frozencloud.wordpress.com/2016/05/03/creating-a-custom-ui-installer-with-wix-burn-bootstrapper/">Creating a custom UI installer with WIX Burn Bootstrapper</a><br />
WPFアプリケーションにブートストラッパ実装例。<br />
<div>
<br /></div>
</div>
<div>
<div>
<a href="https://wrightfully.com/part-1-of-writing-your-own-net-based-installer-with-wix-overview">Part 1 of Writing Your Own .Net-based Installer with WiX - Overview</a></div>
</div>
<div>
EngineとBootstrapperの関係、イベント一覧があります。<br />
<br />
<div style="background-color: white; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-stretch: normal; font-weight: normal; line-height: normal; margin: 0.75em 0px 0px; position: relative;">
<a href="http://blog.xoc.net/2017/04/wix-burn-command-line-and-custom.html">WiX Burn Command Line and Custom Bootstrapper Event Sequence</a></div>
<div style="background-color: white; color: #222222; font-family: Arial, Tahoma, Helvetica, FreeSans, sans-serif; font-stretch: normal; font-weight: normal; line-height: normal; margin: 0.75em 0px 0px; position: relative;">
発生順のイベントリストがあります。</div>
<br /></div>
<div>
<br /></div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-28552284138441209072017-11-07T18:09:00.000+09:002020-06-05T12:51:00.049+09:00WiX toolsetのBootstarpperを試してみた(1)<a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html">多国語対応のmsiのためのBootstarpper作り</a>でWiXのBurnを試してみた。これによる言語切り替えも実現できたのだが、それだけの目的なら<a href="https://ken-plus.blogspot.jp/2017/11/dotnetinstallerbootstarpper.html">dotNetInstallerによるBootstrapper作り</a>の方が面倒がない。とはいえ本格的なインストーラを作る場合には強力なツールなので、Burnについて試したことをまとめておく。<br />
<br />
インストール手順は次のブログを参照<br />
<a href="https://ken-plus.blogspot.com/2017/09/wix-tools-wix-edit.html">VisualStudio 2017 Community & WiX tools & WiX Edit によるWindowsアプリ インストーラ(msi)作成</a><br />
<br />
<b>概要</b><br />
Burnは複数のプロジェクトを一つのバンドルにまとめるもので、そのプロセルは大きくふたつに別れる。インストールを開始する前に実行するBootstarpperと、それに続く一連のインストール実行だ。<br />
<br />
Burnを使ってインストーラを作る場合は、Bootstarpperにより必須環境を整え、そのUIによりユーザがインストール等の条件を設定し、それ以降はその条件に従い実行され、個々のmsiでは設定を変更しないのが基本のようだ。<br />
<br />
msiにUIを表示させることはできるが、長時間かかるインストールの途中で何度もダイアログを表示するのはいただけないし、Bootstarpperが決めた条件をその後のmsiで変更できるようでは、複数のmsi間で不整合が生じうる。<br />
<br />
また、Burnはインストール時のシーケンスを作るだけでなく、アップデート、変更、アンイストールも含めて管理するできるようになっている。そのため、Burnが作るバンドルもレジストリに登録され、コントロールパネルの「プログラムと機能」一覧に表示される。個々のmsiもここに表示することは可能だが、全てバンドルで管理できるようにしておく必要がある。<br />
<br />
開発者のコメントもあります。<br />
<a href="http://robmensching.com/blog/posts/2012/6/25/b-is-for-bundle-and-thats-good-enough-for-me/">B is for Bundle and that's good enough for me.</a><br />
<br />
それでも、BundleのBootstapperからオプションを設定してmsiを起動し、msiのUIでインストール/アンインストールを行うことができる。以下、多言語対応msi用のBundle作りを題材とした手順。<br />
<b><br />
</b> <b>はじめに</b><br />
<br />
試す前にレジストリのバックアップを取っておくことをお勧めする。アンインストールが適切に行なえないと、インストーラでは削除できない項目がレジストリに残ることがある。<br />
<br />
インストーラのログは次の場所に書き出される。<br />
C:\Users\<i>UserName</i>\AppData\Local\Temp\<br />
<br />
<b>Burnによるバンドル作成</b><br />
<ul>
<li>msiプロジェクトを含めるソリューションを開く。</li>
</ul>
<b>Bootstarpperプロジェクト追加</b><br />
<ul>
<li><b>ソリューション右クリック > 追加 > 新しいプロジェクト</b><br />
左ペイン WiX toolset v3 > 中ペイン Bootstapper Project for WiX v3 > OK</li>
<ul>
<li>Bootstrapper1の名前で保存<br />
これでソリューションにBootstarpperプロジェクトが追加される。</li>
</ul>
<li><b>Bundle.wxs変更</b></li>
<ul>
<li><b><span style="font-family: "arial" , "helvetica" , sans-serif;">namespace追加</span></b></li>
<li style="display: inline !important;"><pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"><Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"></span><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">
</span></pre>
</li>
<li style="display: inline !important;"></li>
<ul>
<li>xmlns:balは必須ではないがやがて必要になる</li>
</ul>
<li><b>Bundle要素を変更</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"><Bundle Name="<i>MyAppSetup</i>" Manufacturer="<i>name</i>" ...
UpgradeCode="<i>GUID</i>"></span><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">
</span></pre>
</li>
<ul>
<li>Name: コントロールパネルのプログラムの機能一覧に登録される名前。<br />
exeの名前はプロジェクト > プロパティー > Output nameで設定。</li>
<li>Manufacturer: 空だとエラーになる。</li>
<li>UpgradeCode: msiとは別のものを設定する。</li>
</ul>
<li><b>Chain要素にMsiPackage要素を追加</b></li>
<li style="display: inline !important;"><pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"><Chain>
<MsiPackage SourceFile="..\SetupProject1\bin\Release\WavCutterSetup.msi"
DisplayInternalUI="yes" Visible="no">
<MsiProperty Name="TRANSFORMS" Value="[TRANSFORMS]" />
</MsiPackage>
</Chain></span></pre>
</li>
<li style="display: inline !important;"><pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">
</span></pre>
</li>
<li style="display: inline !important;"><ul>
<li>DisplayInternalUI="yes"の場合、msiのUIを表示(実体はmsiexecの起動パラメータ)</li>
<li style="display: inline !important;"></li>
<li>Visible="yes"の場合、msiもコントロールパネルの「プログラムと機能」一覧に登録される。</li>
</ul>
</li>
</ul>
</ul>
<b>StandardBootstrapperApplication.RtfLicenseによるテスト</b><br />
<ul>
<li><b>BootstrapperApplicationRef要素追加</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"><span style="font-family: "arial" , "helvetica" , sans-serif;"><BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense"></span><span style="font-size: x-small;">
</span></span>
</pre>
</li>
<ul>
<li>StandardBootstrapperApplication: 予め用意されている標準アプリ</li>
<li>RtfLicenseはライセンス表示後Chain中のPackageを実行する。</li>
<ul>
<li>HyperlinkLicenseもあるが、試していない。<br /><br />
</li>
</ul>
</ul>
<li><b>ビルド > MyAppSetup.exe実行</b><br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbcJ7pcnNCrKB1pEMl-JVOPzxAATt09S1d0Glc4wMidObGH-zORD7jhg1QqhJ-YSiVpWb4NqzlGpWsqZUTaxBDhxTovGg-IAwcHIBPajco__ownaL3HF1GjYXYmk4T2OpOS86LTTQ3Mw/s1600/%25E7%2594%25BB%25E5%2583%258F2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="297" data-original-width="481" height="197" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhbcJ7pcnNCrKB1pEMl-JVOPzxAATt09S1d0Glc4wMidObGH-zORD7jhg1QqhJ-YSiVpWb4NqzlGpWsqZUTaxBDhxTovGg-IAwcHIBPajco__ownaL3HF1GjYXYmk4T2OpOS86LTTQ3Mw/s320/%25E7%2594%25BB%25E5%2583%258F2.png" width="320" /></a></div>
<div class="separator" style="clear: both;">
ライセンスに同意し、Installをクリックするとmsiが実行される。</div>
<div class="separator" style="clear: both;">
msiが再度ライセンス同意を求める。</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
</li>
<li><div class="separator" style="clear: both;">
<b>「プログラムと機能」に登録</b></div>
上記設定の場合、コントロールパネルの「プログラムと機能」一覧に<i>MyAppSetup</i>が登録される。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_xsqdkIvYrZ_a3Dxwd69B2OMeZd4pERxhMCKElqMry-kv99nfrARL-w-CFWWo5JRGQv_7GY0rNTfkyTsjbOYD3DGuw8MiSoIGdVUcE7mawl_Rms4XBmWiuij3KOwOzX9OTF_XbQvxDA/s1600/%25E7%2594%25BB%25E5%2583%258F3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="247" data-original-width="525" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh_xsqdkIvYrZ_a3Dxwd69B2OMeZd4pERxhMCKElqMry-kv99nfrARL-w-CFWWo5JRGQv_7GY0rNTfkyTsjbOYD3DGuw8MiSoIGdVUcE7mawl_Rms4XBmWiuij3KOwOzX9OTF_XbQvxDA/s320/%25E7%2594%25BB%25E5%2583%258F3.png" width="320" /></a><br />
</li>
</ul>
<ul>
<li><div class="separator" style="clear: both;">
<b><i>MyAppSetup</i>ダブルクリック</b></div>
MyAppSetupダブルクリックで変更/アンインストールが実行される。<br />
「Repair」「Uninstall」はBundleとしてのものなので、msiがこれらに対応していなくてもが表示される。<br />
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzmfteQrVKVr6IzcL-XfdO4m9X0k5E_M4wa0z9xV-FrHFyD1253JEHKgugM_th7zSnoRlkWYCzZ0VoGKOuhxo_Ivg1MQS1_DFOBSTqwsTmihMJr_9rVT4aqTYkgVvbH0I30TAaXT0qEA/s1600/%25E7%2594%25BB%25E5%2583%258F4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="300" data-original-width="482" height="199" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhzmfteQrVKVr6IzcL-XfdO4m9X0k5E_M4wa0z9xV-FrHFyD1253JEHKgugM_th7zSnoRlkWYCzZ0VoGKOuhxo_Ivg1MQS1_DFOBSTqwsTmihMJr_9rVT4aqTYkgVvbH0I30TAaXT0qEA/s320/%25E7%2594%25BB%25E5%2583%258F4.png" width="320" /></a><br />
</li>
<li><div class="separator" style="clear: both;">
<b>削除実行</b></div>
「Uninstall」クリックで、サイレントでmsiによる削除が実行される。<br />
</li>
</ul>
<div>
Bundle想定しているインストールの手順は、概ねこのようなものと考えられる。</div>
<div>
<br /></div>
<div>
ここでは何も設定していないが、本来はDOT.NET Frameworkのチェック、インストールなど、必須環境を整える作業を行ってから、Chain内のインストールが順次行われる。</div>
<div>
<br /></div>
<div>
ちなみに、msiでは必須コンポネントの存在有無チェックは行えるが、無い場合はメッセージ表示でインストールを中断する。</div>
<div>
<br /></div>
<div>
<b>アンインストール</b></div>
<div>
<br /></div>
<div>
この<i>MyAppSetup</i>を二度実行した場合、既にBundleが登録されているため、コントロールパネルからの場合と同様に「Modify Setup」のダイアログとなる。</div>
<div>
<br /></div>
<div>
msiにスタートメニューへのアンインストールボタン追加が設定されている場合は、そのボタンも追加される。先にmsiによるアンインストールを行うと、このアプリは削除されるがBundleは残っているため、再度MyAppSetupを実行すると「Modify Setup」のダイアログとなる。Bundleでアンインストールを行えば、アプリ削除後であってもBundleが削除される。msiがひとつだけだと違和感はあるが、Bundleの動作としては問題ない。</div>
<div>
<br />
MsiPackageでVisible="yes"とすると、msiも「プログラムと機能」一覧に追加されるので、これと同じことが起こる。<br />
<br /></div>
<div>
<b>ManagedBootstrapperApplicationHostによる機能追加</b></div>
<div>
<div>
RtfLicenseは表示するライセンス、ダイアログのスタイルなどをカスタマイズできるが、UIに機能を追加することはできない。これが必要な場合はManagedBootstrapperApplicationHostを使用する。</div>
<br />
<div>
ManagedBootstrapperApplicationHost は BootstrapperApplication のサブクラスを含むクラスライブラリ(.dll)を読み込み、そのBootstrapperApplication インスタンスのイベントハンドを順次呼び出すことで、インストール環境を整える。</div>
<div>
<ul>
<li><b>クラスライブラリ追加</b><br />
ソリューション右クリック > 追加 > 新しいプロジェクト > Visual C# > クラスライブラリ(.NET Framework)</li>
<ul>
<li>プロジェクト名、アッセンブリ名=<i>ClassLibrary1で追加。<br />
追加するクラスはMyBootstrapper.csとする。</i></li>
<li>参照追加<br />
<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"> C:\Program Files (x86)\WiX Toolset v3.11\SDK\BootstrapperCore.dll<br />
</span></li>
<li>次のconfigファイルを<u><i>Bootstrapper1</i>プロジェクトへ</u>追加<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">C:\Program Files (x86)\WiX Toolset v3.11\SDK\BootstrapperCore.config</span><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">
</span></pre>
</li>
<li>BootstrapperCore.config 変更<br />
<span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"> <host assemblyName="<i>ClassLibrary1</i>"></host><br />
</span></li>
</ul>
<li><b>BootstrapperApplicationRef の設定を変更</b></li>
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;"><BootstrapperApplicationRef Id='ManagedBootstrapperApplicationHost'>
<Payload SourceFile="..\ClassLibrary1\bin\Release\ClassLibrary1.dll" />
<Payload Name="BootstrapperCore.config" SourceFile="BootstrapperCore.config" />
</BootstrapperApplicationRef>
<WixVariable Id="WixMbaPrereqPackageId" Value="Netfx4Full" />
<WixVariable Id="WixMbaPrereqLicenseUrl" Value="NetfxLicense.rtf" /></span>
</pre>
<ul>
<li>WixMbaPrereqPackageId、WixMbaPrereqLicenseUrl が設定されていないとエラーになる。</li>
</ul>
<li><i><b>MyBootstrapper.csの実装</b></i></li>
<ul></ul>
<ul>
<li><b>namespace<i>行の前にアノテーション追加</i></b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">[assembly:BootstrapperApplication(typeof(MySetup.MyBootstrapper))]
namespace MySetup
{
public class MyBootstrapper : BootstrapperApplication
{ .... }
}</span><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">
</span><span style="font-family: "arial" , "helvetica" , sans-serif;">
</span></pre>
</li>
</ul>
<div>
<ul>
<li><b>Runメソッド追加</b><br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">public class MyBootstrapper : BootstrapperApplication
protected overridevoid Run()
{
Engine.Quit(0);
}</span><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: x-small;">
</span></pre>
</li>
</ul>
<ul><ul>
<li>Run()の中でUI表示や、インストール条件設定など行う。</li>
</ul>
</ul>
<ul><ul>
<li>Engine.Quit(0)でexeの終了処理に入る。ここで実行すると実際には意味がないが、これがないとバックグランドプロセスが残るのでテスト中は適当なところでEngine.Quit(0)を呼ぶ。もし呼びそこなうと、タスクマネージャーでプロセスを終了させることになる。</li>
</ul>
<li><b>イベントハンドラ追加</b><br />
少なくとも次のふたつのイベントハンドラを追加する。<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif; font-size: xx-small;">protected override void Run()
{
PlanComplete += OnPlanComplete;
ApplyComplete += OnApplyComplete;
if (Command.Action == LaunchAction.Install)
{
Engine.Plan(LaunchAction.Install);
}
else
{
//「プログラムと機能」一覧から起動した場合
Engine.Plan(LaunchAction.Uninstall);
}
//Engine.Quit(0)はここでは呼ばない。
}
private void OnPlanComplete(object sender, PlanCompleteEventArgs e)
{
if (e.Status >= 0)
{
Engine.Apply(System.IntPtr.Zero);
}
else
{
Engine.Quit(0);
}
}
private void OnApplyComplete(object sender, ApplyCompleteEventArgs e)
{
Engine.Quit(0);
}</span>
</pre>
</li>
</ul>
</div>
</ul>
ここまでで msi 単独のときと近い動作になるが、MyAppSetup.exe 起動時の Install / Uninstall の切り分けをコマンドラインパラメータからセットされる LaunchAction で行っているため、MyAppSetup.exe を繰り返し起動したとき常にInstallしようとし、結果二度目以降は何もせずに終了する。 </div>
</div>
<div>
これについては<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_10.html">次回</a>へ続く。<br />
<br />
<b>関連ブログ</b><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html">VisualStudio 2017 Community & WiX tools & WiX Edit によるWindowsアプリ インストーラ(msi)作成</a></span><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/dotnetinstallerbootstarpper.html">dotNetInstallerによるシンプルBootstarpper作成</a></span><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_10.html" style="font-family: Arial, Helvetica, sans-serif;">WiX toolsetのBootstarpperを試してみた(2)Detect追加</a><br />
<span style="font-family: "arial" , "helvetica" , sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_46.html">WiX toolsetのBootstarpperを試してみた(3)msiexecパラメータ設定</a></span><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpperui.html" style="font-family: Arial, Helvetica, sans-serif;">WiX toolsetのBootstarpperを試してみた(4)UI追加</a><br />
<br /></div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-72494930710424353802017-11-06T12:08:00.004+09:002017-11-15T15:10:13.304+09:00dotNetInstallerによるシンプルBootstarpper作成前回で多言語対応のmsiを作成したので、コマンドラインオプションを設定してmsi起動するBootstarpper作りを試みた。<br />
<br />
本格的なものを作るならWiXのBurnを用いてBundleを作ることができるが、その場合はUIをBundle側のBootstrapperに移し、msiはBootstrapperの設定にしたがってUIなしで実行するのが本道のようだ。となると、せっかくmsiを多国語対応した意味がなくなるので<br />
、このmsiを利用するシンプルなBootstarpperを作りを試みた。<br />
<br />
ちなみにWiXでmsiにActionを追加することができるが、これはmsiが起動したあとで使われるので、起動時の言語切り替えには使えなかった。<br />
<br />
まずはmsiとは別のexeを作り、そこからWindowsのCulture設定に従いmsiを起動する方法。例えば次のようなコードでコンソールアプリを作ればよい。<br />
<br />
<pre><span style="font-family: "arial" , "helvetica" , sans-serif;">static void Main(string[] args)
{
FileInfo msiFileInfo = new FileInfo(Directory.GetParent(Assembly.GetExecutingAssembly().Location) + "\\MyAppSetup.msi");
if (!CultureInfo.Exists) {
if (CultureInfo.CurrentCulture.Name == "ja-JP")
{
System.Diagnostics.Process.Start(msiFileInfo.FullName, "TRANSFORMS=\":ja-JP.mst\"");
}
else
{
System.Diagnostics.Process.Start(msiFileInfo.FullName);
}
}
</span></pre>
<br />
この方法の問題点はmsiとexeの二つが存在し、msiを直接起動することもできてしまうことだ。言語切り替えだけであれば実質的な問題はないとも言えるが、できれば一本化したい。<br />
<br />
<b>dotNetInstaller </b><br />
<br />
探してみたところ dotNetInstaller というオープンソフトがあった。公式ページではV2.3(Windows8対応)までだが、GitHubからはV2.4(Window10 対応)をダウンロードできる。<br />
<br />
<b>dotNetInstallerダウンロード</b><br />
<a href="https://github.com/dblock/dotnetinstaller">git.hubサイト (dotNetInstaller 2.4</a>)<br />
<a href="http://dblock.github.io/dotnetinstaller/">dotNetInstaller公式サイト</a><br />
<br />
dotNetInstallerも本格的なインストーラ作成に対応しているが、ここでは単に言語切り替えを実現するだけ。dotNetInstallerの設定でmsiをsetup.exeに組み込みこむ。setup.exe実行で、これをTempフォルダに展開し、展開後msiexecでmsiを実行する。このとき、日本語の場合、そうでない場合の二つの構成を用意しておき、言語設定に応じて使い分ける。<br />
<br />
この方法については次のWebページで紹介されており、サンプルもダウンロード可能。<br />
<div>
<a href="https://thecodeking.co.uk/article/creating-a-localized-windows-installer-bootstrapper-part-4/">Part 4: Creating a Wix localised installer & bootstrapper</a></div>
<div>
<br /></div>
<div>
dotNetInstaller には非常に多くの設定がありますが、今回関係したところいがいはよくわかりません。<br />
<br />
dotNetInstallerはconfigurationファイルを作成するInstaller Editorと、exeを作るコマンド InstallerLinker.exe からなる。</div>
<br />
<b>Installer Editor / </b><b>Configurationファイル作成</b><br />
<br />
<b>準備</b><br />
手順を単純化するため、どこかに作業フォルダを作成し、<i>MySetup.msi</i> をコピーする。<br />
コマンドプロンプトを起動し、そのフォルダに移動しておく。InstallerLinker.exe 起動はここから行うことし、以下の定数#APPPATHはこの場所を指す。<br />
<br />
<b>dotNetInstaller起動</b><br />
dotNetInstallerをインストール後、スタートメニューからInstaller Editor起動。<br />
<br />
<b>File > New</b><br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7SZfEcFCzpv9-dDXeDBKDfbTeg3n7Hxag0AAzDaDC_M-4lxGDlxOhV6Y4QmlR013PFEyfuHYQTq4qN6QWy0E1S1ljSSHqecGlRMOecawVqXNbvX2ZU19dNY71iHyPcWxQHa7TY9Xehw/s1600/%25E7%2594%25BB%25E5%2583%258F2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="94" data-original-width="623" height="60" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh7SZfEcFCzpv9-dDXeDBKDfbTeg3n7Hxag0AAzDaDC_M-4lxGDlxOhV6Y4QmlR013PFEyfuHYQTq4qN6QWy0E1S1ljSSHqecGlRMOecawVqXNbvX2ZU19dNY71iHyPcWxQHa7TY9Xehw/s400/%25E7%2594%25BB%25E5%2583%258F2.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>Logging > log_enabledをTrueに変更(推奨)<br />
log_fileの場所に出力される。</li>
<ul>
<li>#TEMPPATHは標準では次の場所<br />
C:\Users\<i>UserName</i>\AppData\Local\Temp</li>
</ul>
<li>UI > ui_levelをsilentに変更(デバッグ中はbasicでもよい)</li>
<li>Locale > lcidtype を User(またはUserExe以外)に変更</li>
</ul>
<b>Edit > Add > Configurations > Setup Configuration</b><br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWDBL8BOW46RVxEhvVV3KWR5FAA0ffauL0_u4Ecd3ls12k5lkWv20Beyi_QC5_Usx_3_Nt0-E3EJ_Rz-J4ZbsA2HL30KQ5ar1ZvI26h78dPUcfHtzp0iqg7VFpnQ3MvBHlCAQUTK4hhA/s1600/%25E7%2594%25BB%25E5%2583%258F4.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="100" data-original-width="620" height="63" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiWDBL8BOW46RVxEhvVV3KWR5FAA0ffauL0_u4Ecd3ls12k5lkWv20Beyi_QC5_Usx_3_Nt0-E3EJ_Rz-J4ZbsA2HL30KQ5ar1ZvI26h78dPUcfHtzp0iqg7VFpnQ3MvBHlCAQUTK4hhA/s400/%25E7%2594%25BB%25E5%2583%258F4.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>Language > lcid_filterを”1041”(日本語)に設定</li>
<li>Runtime > complete_commandに次のコマンドを入力<br />
msiexec /i #CABPATH\<i>MySetup.msi</i> TRANSFORMS=":ja-JP.mst"</li>
<ul>
<li>#CABPATHはdotNetInstallerが作成するTempフォルダ。標準では次の場所。<br />
C:\Users\<i>UserName</i>\AppData\Local\Temp\{<i>GUID</i>}</li>
<li>"ja-JP"の部分は定義済み定数”#OSLOCALE”で置換可能だが、msiに組み込まれているmstと一致しないとエラーになる。</li>
<li>UIを表示させる場合は、少なくともメッセージのAPPLICATION_NAMEを変更する。</li>
</ul>
<li>Main Dialog > dialog_show_installed をFalseに変更</li>
<li>Runtime > show_progress_dialogをFalseに変更(Trueでもよい)</li>
</ul>
<b>"install:"を右クリック > Add > Embed > Embed File</b><br />
<div class="separator" style="clear: both; text-align: left;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhShh3OIfHWUmR00A9XLvmQXCmRcV0XJFstgyBFzJRF3UyD0EzJKgx2tirrBE8AfEMdzE5rM7i2-vgnMJndoaJ4NUXKk84F3gf4AiaX3jweBQElPEs86SGGMeVV1iTJyGXtzqqhmFegFQ/s1600/%25E7%2594%25BB%25E5%2583%258F2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="213" data-original-width="762" height="108" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhShh3OIfHWUmR00A9XLvmQXCmRcV0XJFstgyBFzJRF3UyD0EzJKgx2tirrBE8AfEMdzE5rM7i2-vgnMJndoaJ4NUXKk84F3gf4AiaX3jweBQElPEs86SGGMeVV1iTJyGXtzqqhmFegFQ/s400/%25E7%2594%25BB%25E5%2583%258F2.png" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<ul>
<li>sourcefilepathに次のパスを入力<br />
#APPPATH\<i>MySetup.msi</i></li>
<li>targetfilepathに<i>MySetup.msiを入力。<br />
#CABPATHからの相対パスで、別の名前でもよく、またサブフォルダを加えることもできるが、</i>msiexec のパラメータ<i>と一致させること。</i></li>
</ul>
<b>もうひとつSetup Configurationを追加</b><br />
<ul>
<li>Setup Configuration以下の手順を繰り返し、もうひとつSetup Configurationを追加する。</li>
<ul>
<li>Language > lcid_filterを"!1041"(日本語以外)に設定</li>
<li>Runtime > complete_commandに次のコマンドを入力(TRANSFORMSなし)<br />
msiexec /i #CABPATH\WavCutterSetup.msi </li>
</ul>
</ul>
<b>configuration.xml保存</b><br />
<ul>
<li>File > Save または Save As で準備で作成したフォルダ内に保存</li>
</ul>
<b>InstallerLinker.exe実行 / setup.exe作成</b><br />
<ul>
<li>標準では次のフォルダにインストールされている。<br />
C:\Program Files (x86)\dotNetInstaller\bin</li>
<li>次の要領でInstallerLinker.exeを実行する。<br />
>set linkerFolder="C:\Program Files (x86)\dotNetInstaller\bin"<br />
>%linkerFolder%\InstallerLinker.exe /o:setup.exe /t:%linkerFolder%\dotNetInstaller.exe /c:configuration.xml /v+</li>
<li>setup.exeが出力される。</li>
</ul>
<div>
関連ブログ<br />
<a href="https://ken-plus.blogspot.jp/2017/09/wix-tools-wix-edit.html"><span style="font-family: Arial, Helvetica, sans-serif;">VisualStudio 2017 Community & WiX tools & WiX Edit によるWindowsアプリ インストーラ(msi)作成</span></a><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolset-msi.html">WiX toolset msi ダイアログ多国語対応</a><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper.html">WiX toolsetのBootstarpperを試してみた(1)</a></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_10.html">WiX toolsetのBootstarpperを試してみた(2)Detect追加</a></span><br />
<span style="font-family: Arial, Helvetica, sans-serif;"><a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpper_46.html">WiX toolsetのBootstarpperを試してみた(3)msiexecパラメータ設定</a></span><br />
<a href="https://ken-plus.blogspot.jp/2017/11/wix-toolsetbootstarpperui.html"><span style="font-family: Arial, Helvetica, sans-serif;">WiX toolsetのBootstarpperを試してみた(4)UI追加</span></a></div>
Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-15929426216286943392017-10-20T22:47:00.000+09:002017-11-07T08:46:57.841+09:00クラスメソッド +initilalize について+initializeが複数回呼ばれることがあるため、[super initialize]を呼ぶべきかどうかも含めて調べてみた。<br />
結論としては、[super initialize]は呼ぶ必要はないが、空でも+initializeを実装しておいた方が良い場合がある。<br />
<br />
クラスが初めて参照された時に+initializeが呼ばれるが、あるサブクラスのインスタンスを作成すると、そのクラス階層の上位からinitializeが呼ばれる。<br />
<br />
例えば、次のようなクラス階層を作る。<br />
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff}
</style> <br />
<div class="p1"><span class="s1"><span style="font-size: small;"><br />
</span></span></div><div class="p1"><span style="font-size: small;"><span class="s1"> @interface</span> MyClass1 : <span class="s2">NSObject</span></span></div><div class="p1"><span style="font-size: small;"><span class="s1"> @interface</span> MyClass2 : MyClass1</span></div><div class="p1"><span style="font-size: small;"><span class="s1"> @interface</span> MyClass3 : MyClass2</span></div><div class="p1"></div><div class="p1"><span style="font-size: small;">各々に次のような+initializeメソッドを実装する。</span></div><div class="p1"><span style="font-size: small;"> + (<span class="s1">void</span>)initialize</span></div><div class="p1"><span style="font-size: small;"> {</span></div><div class="p2"><span style="font-size: small;"><span class="s2"><span class="Apple-converted-space"> </span></span><span class="s3">NSLog</span><span class="s2">(</span>@"MyClass1.initialize"<span class="s2">);</span></span></div><div class="p1"><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff}
p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff}
</style> </div><div class="p1"><span style="font-size: small;"> }</span></div><div class="p1"><span style="font-size: small;"><br />
</span></div><div class="p1"><span style="font-size: small;">どこかでMyClass3のインスタンスを作る。</span></div><div class="p1"><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff}
</style> </div><div class="p1"><span style="font-size: small;"><span class="s1"> MyClass3</span> *myClass3 = [[<span class="s1">MyClass3</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></div><span style="font-size: small;"><br />
</span><span style="font-size: small;">この場合、次のようにログが書き出され、クラス階層の上位から+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeメソッドが呼ばれていることがわかる。</span><br />
<span style="color: black;"><span class="s1"> <span style="color: black;">MyClass1.initialize</span></span></span><br />
<span style="color: black;"><span class="s1"> <span style="color: black;">MyClass2.initialize</span></span></span><br />
<span style="color: black;"><span class="s1"><span style="color: black;"> MyClass3.initialize</span></span></span><br />
<span class="s1"><span style="color: black;"><br />
</span></span> <span style="font-variant-ligatures: no-common-ligatures;">次のように順次上位のクラスのインスタンスを作ってみる。</span><br />
<div class="p1"><span style="font-size: small;"><span class="s1"> MyClass1</span> *myClass1 = [[<span class="s1">MyClass1</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></div><div class="p1"><span style="font-size: small;"><span class="s2"> NSLog</span>(<span class="s3">@"%@"</span>, myClass1);</span></div><div class="p1"><span style="font-size: small;"><span class="s1"> MyClass2</span> *myClass2 = [[<span class="s1">MyClass2</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></div><div class="p1"><span style="font-size: small;"><span class="s2"> NSLog</span>(<span class="s3">@"%@"</span>, myClass2);</span></div><div class="p1"><span style="font-size: small;"><span class="s1"> MyClass3</span> *myClass3 = [[<span class="s1">MyClass3</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></div><span class="s1"> <style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff}
</style> </span><br />
<div class="p1"><span style="font-size: small;"><span class="s2"> NSLog</span>(<span class="s3">@"%@"</span>, myClass3);</span></div><span class="s1"><br />
</span> <span class="s1"><span style="color: black;">この場合は次のようにログが書き出される。</span></span><br />
<div class="p1"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></div><div class="p1"><span class="s1"><span style="color: black; font-size: small;"> <MyClass1: 0x6000000089c0></span></span></div><div class="p1"><span class="s1"><span style="color: black; font-size: small;"> MyClass2.initialize</span></span></div><div class="p1"><span class="s1"><span style="color: black; font-size: small;"> <MyClass2: 0x600000008940></span></span></div><div class="p1"><span class="s1"><span style="color: black; font-size: small;"> MyClass3.initialize</span></span></div><span class="s1"><span style="color: black;"> <style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style> </span></span><br />
<div class="p1"><span class="s1"><span style="color: black; font-size: small;"> <MyClass3: 0x6000000089d0></span></span></div><span class="s1"><br />
</span> <span style="font-variant-ligatures: no-common-ligatures;">すでに+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeが呼ばれているクラスについては、繰り返し</span><span style="font-variant-ligatures: no-common-ligatures;">+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeが</span><span style="font-variant-ligatures: no-common-ligatures;">呼ばれない。</span><br />
<span style="font-variant-ligatures: no-common-ligatures;"><br />
</span> <span style="font-variant-ligatures: no-common-ligatures;">ちなみに次の順序でインスンタンスを作ると、</span><br />
<div class="p1"><span style="font-size: small;"><span class="s1"><span style="color: black;"><span style="font-variant-ligatures: normal;"> M</span></span>yClass3</span> *myClass3 = [[<span class="s1">MyClass3</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></div><div class="p1"><span style="font-size: small;"><span class="s2"><span style="color: black;"> </span>NSLog</span>(<span class="s3">@"%@"</span>, myClass3);</span></div><div class="p1"><span style="font-size: small;"><span class="s1"><span style="color: black;"><span style="font-variant-ligatures: normal;"> </span></span>MyClass1</span> *myClass1 = [[<span class="s1">MyClass1</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></div><div class="p1"><span style="font-size: small;"><span class="s2"><span style="color: black;"> </span>NSLog</span>(<span class="s3">@"%@"</span>, myClass1);</span></div><div class="p1"><span style="font-size: small;"><span class="s1"><span style="color: black;"><span style="font-variant-ligatures: normal;"> </span></span>MyClass2</span> *myClass2 = [[<span class="s1">MyClass2</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></div><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000; background-color: #ffffff}
</style> <br />
<div class="p1"><span style="font-size: small;"><span class="s2"><span style="color: black;"> </span>NSLog</span>(<span class="s3">@"%@"</span>, myClass2);</span></div><div class="p1"><span style="font-size: small;"><br />
</span></div><div class="p1"><span style="font-size: small;">ログは次のようになる。</span></div><div class="p1"><span class="s1"><span style="font-size: small;"> MyClass1.initialize</span></span></div><div class="p1"><span class="s1"><span style="font-size: small;"> MyClass2.initialize</span></span></div><div class="p1"><span class="s1"><span style="font-size: small;"> MyClass3.initialize</span></span></div><div class="p1"><span class="s1"><span style="font-size: small;"> <MyClass3: 0x60000000aa80></span></span></div><div class="p1"><span class="s1"><span style="font-size: small;"> <MyClass1: 0x60000000aad0></span></span></div><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style> <br />
<div class="p1"><span class="s1"><span style="font-size: small;"> <MyClass2: 0x60000000aae0></span></span></div><div class="p1"><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style> </div><div><br />
<span class="s2"></span> <span class="s2"> </span> <br />
<div><span class="s2"><span style="color: black;"><span style="background-color: white; font-family: "menlo";">myClass3を作った時に</span><span style="background-color: white; font-family: "menlo";">MyClass1、</span><span style="background-color: white; font-family: "menlo";">MyClass2、</span><span style="background-color: white; font-family: "menlo";">MyClass3の+</span><span style="background-color: white; font-family: "menlo";">initializeが順次呼ばれており、それ以降の</span><span style="background-color: white; font-family: "menlo";">myClass1、</span><span style="background-color: white; font-family: "menlo";">myClass2作成時には呼ばれない。</span></span></span></div><span class="s2"> </span> <br />
<div><span class="s2"><span style="background-color: white; color: black; font-family: "menlo";"><br />
</span></span></div><span class="s2"> </span> <br />
<div><div class="p1"><span class="s2"><span style="font-size: small;">さて、+initializeメソッドで[super initialize]を呼ぶように変えてみる。</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> + (<span class="s1">void</span>)initialize</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> {</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> [super initialize];</span></span></div><div class="p2"><span class="s2"><span style="color: black; font-size: small;"><span class="s2"><span class="Apple-converted-space"> </span></span><span style="color: black;"><span class="s3"><span style="color: black;">NSLog</span></span><span class="s2">(</span></span>@"MyClass1.initialize"<span class="s2">);</span></span></span></div><div class="p1"></div><div class="p1"><span class="s2"><span style="font-size: small;"> }</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><br />
</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;">すると、</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span class="s1"> MyClass3</span> *myClass3 = [[<span class="s1">MyClass3</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></span></div><div><span class="s2"><span style="color: black; font-size: small;"><br />
</span></span></div><div><span class="s2"><span style="color: black;">の場合に、次のように<span style="background-color: white; font-family: "menlo";">initializeが呼ばれるようになる。</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass2.initialize</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass2.initialize</span></span></span></div><div class="p1"><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style><span class="s2"> </span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass3.initialize</span></span></span></div><div class="p1"><span class="s2"><br />
</span></div><div class="p1"><span class="s2"><span style="font-size: small;">MyClass1、MyClass2、MyClass3の順に+<span style="font-variant-ligatures: no-common-ligatures;">initializeが呼ばれるが、</span>MyClass2の時にsuperの<span style="font-variant-ligatures: no-common-ligatures;">MyClass1が再度呼ばれ、</span><span style="font-variant-ligatures: no-common-ligatures;">MyClass3の時に同様に</span><span style="font-variant-ligatures: no-common-ligatures;">MyClass2、</span><span style="font-variant-ligatures: no-common-ligatures;">MyClass1が再度呼ばれる。</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;"><b><br />
</b></span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;">ということで、</span><span style="background-color: transparent; font-size: small;">[super initialize]を呼ぶと無駄な呼び出しが繰り返されることになり、実装によっては不具合を生じる可能性もある。</span></span></div><div class="p1"><span class="s2"><br />
</span></div><div class="p1"><span class="s2"><span style="font-size: small;">さてここで、[super initialize]は削除し、さらに<span style="font-variant-ligatures: no-common-ligatures;">MyClass3の+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeを削除してみる。</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;"><br />
</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;">すると、</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span class="s1"> MyClass3</span> *myClass3 = [[<span class="s1">MyClass3</span> <span class="s2">alloc</span>] <span class="s2">init</span>];</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><br />
</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;">の場合のログは次のようになる。</span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></span></div><div class="p1"><span class="s2"><span style="font-variant-ligatures: no-common-ligatures;"><span style="font-size: small;"> MyClass2.initialize</span></span></span></div><div class="p1"><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style><span class="s2"> </span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass2.initialize</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"><br />
</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;">superクラスの</span><span style="font-variant-ligatures: no-common-ligatures;">MyClass1、</span><span style="font-variant-ligatures: no-common-ligatures;">MyClass2の+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeが順次呼ばれたあと、</span>myClass3の<span style="background-color: transparent; font-variant-ligatures: no-common-ligatures;">+</span><span style="background-color: transparent; font-variant-ligatures: no-common-ligatures;">initializeが呼ばれようとするが、これが実装されていない場合はそのsuperクラスの</span><span style="font-variant-ligatures: no-common-ligatures;">initializeが呼ばれる。</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;"><br />
</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;">サブクラスが</span>+<span style="font-variant-ligatures: no-common-ligatures;">initializeを実装していない場合、そのsup</span></span><span style="font-size: small; font-variant-ligatures: no-common-ligatures;">erクラスの</span><span style="font-size: small; font-variant-ligatures: no-common-ligatures;">initializeが複数回呼ばれることになる。</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;"><br />
</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;">MyClass2には</span><span style="font-variant-ligatures: no-common-ligatures;">+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeが実装されているが</span>[super initialize]はないため、<span style="font-variant-ligatures: no-common-ligatures;">MyClass1はここでは再度呼ばれない。</span></span></span></div><div class="p1"><span class="s2"><br />
</span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;">さらに</span><span style="font-variant-ligatures: no-common-ligatures;">MyClass2の+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeを削除すると、ログは次のようになる。</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></span></div><div class="p1"><style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Menlo; color: #000000}
span.s1 {font-variant-ligatures: no-common-ligatures}
</style><span class="s2"> </span></div><div class="p1"><span class="s2"><span class="s1"><span style="color: black; font-size: small;"> MyClass1.initialize</span></span></span></div><div class="p1"><span class="s2"><span class="s1"><b><span style="font-size: small;"><br />
</span></b></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span class="s1"><span style="color: black; font-variant-ligatures: normal;">myClass2、</span></span>myClass3は<span style="font-variant-ligatures: no-common-ligatures;">+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeがないのでログは書かないが、+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeがないのでsuperを辿り、</span></span>MyClass1の<span style="font-variant-ligatures: no-common-ligatures;">+</span><span style="font-variant-ligatures: no-common-ligatures;">initialize</span><span style="font-variant-ligatures: no-common-ligatures;">が実行され、</span><span style="font-variant-ligatures: no-common-ligatures;">MyClass1のログが3回書かれる。</span></span></div><div class="p1"><span class="s2"><span class="s1"><b><br />
</b></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;">このようにsuperの</span></span><span style="font-variant-ligatures: no-common-ligatures;">+</span><span style="font-variant-ligatures: no-common-ligatures;">initializeを実行するのは</span>、ダイナミックにクラスを生成する場合の初期化に必要なためらしい。</span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;"><br />
</span></span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><span style="font-variant-ligatures: no-common-ligatures;">ということで、</span>[super initialize]を書かなくても上位のクラスから+initializeが呼ばれるので、書く必要はない。むしろ書かない方が良い。</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"><br />
</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;">一方、+initializeを実装しない場合は上位クラスの+initializeが複数回呼ばれる。サブクラスが必ずしも+initializeを実装するとは限らないので、+initializeでは複数回呼ばれても問題ないような実装にする必要がある</span><span style="font-size: small;">。また、特別な理由がなければ、空の</span><span style="font-size: small;">+initialize </span></span></div><div class="p1"><span class="s2"><span style="font-size: small;">を実装しておいた方が</span>良いように思える。</span></div><div class="p1"><span class="s2"><span style="font-size: small;"><br />
</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;">もし</span>+initializeが一度だけしか実行されないようにする必要がある場合は、次のような方法がある。</span></div><div class="p1"><span class="s2"><span style="font-size: small;"> + (void)initialize</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> {</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> static dispatch_once_t once;</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> dispatch_once(&once, ^{</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> ......</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> });</span></span></div><div class="p1"><span class="s2"><span style="font-size: small;"> }</span></span></div></div><span class="s2"> </span></div>Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0tag:blogger.com,1999:blog-6538117324271148932.post-45286183862326030212017-10-15T11:04:00.005+09:002017-10-25T15:37:18.290+09:00Could not load the "imageName.png" image referenced from a nib in the bundle with identifier ...<b>Could not load the "imageName.png" image referenced from a nib in the bundle with identifier ...</b><br />
<b><br /></b>
pngをプロヘクトに追加するとInterfaceBuilderではUIにimageを設定できるようになるが、それだけではビルド時にbundleにコピーされないため、実行時にリソースが見つけられず発生する。<br />
<br />
プロジェクトビュー > Target > BuildPhases > Copy Bundle Resources<br />
エラーが発生している画像ファイルを追加する。Kenji Nakamurahttp://www.blogger.com/profile/15945949488491632185noreply@blogger.com0