目次
dotNET
user.configの保存先
OS | フォルダ |
---|---|
Vista,Windows7~ | C:\Users\(ユーザ名)\AppData\Local\<CompanyName>\<ProductName>\<ProductVersion>\user.config |
XP | C:\Documents and Settings\(ユーザ名)\Local Settings\Application Data\<CompanyName>\<ProductName>\<ProductVersion>\user.config |
Windowsのディレクトリ構成ガイドライン
ガイドライン抜粋
Program Files、ユーザー固有・アプリケーション共有データ
- C:\Program Files
プログラム、ソフトウェアコンポーネント置き場
通常ユーザーはこの場所に書き込み権を持たないため、ユーザーデータやアプリケーションデータはここへ置くべきでない。
- C:\ProgramData:
コンピューター上のすべてのユーザーが共有するアプリケーションデータ置き場
C:\Users\<ユーザー名>\AppData:
ユーザー固有のアプリケーションデータ置き場
AppData以下はさらに階層構造を持つ
- C:\Uses\<ユーザー名>\AppData\Roaming
コンピュータに依存しないユーザー固有のアプリケーションデータ置き場
アプリケーションデータのうち、ユーザーカスタマイズ情報などで、ユーザーの操作を伴い変更するもの
- C:\Uses\<ユーザー名>\AppData\Local
このコンピュータに固有のユーザー固有のアプリケーションデータ置き場
アプリケーションデータのうち、一時的で破棄されてもアプリケーション動作に支障のないもの(ログ、デバッグ情報など)
コンピュータに依存しないユーザー固有のアプリケーションデータでも、ユーザーの操作なしに再生成できるデータ(ユーザーが作成するカスタマイズ情報や設定情報は含まない)
- C:\Users\<ユーザー名>\AppData\LocalLow
ユーザー固有の特権(管理者権限)なしに扱えるアプリケーションデータ
Environment.SpecialFolder 列挙体のメンバ | 環境変数名 | 場所の例 |
---|---|---|
UserProfile | %USERPROFILE% | C:\Users\<ユーザー名>\ |
ApplicationData | %APPDATA% | C:\Users\<ユーザー名>\AppData\Roaming |
なし | %TEMP% | C:\Users\<ユーザー名>\AppData\Local\Temp |
LocalApplicationData | %LOCALAPPDATA% | C:\Users\<ユーザー名>\AppData\Local |
なし(配下はある) | %PUBLIC% | C:\Users\Public |
CommonApplicationData | %PROGRAMDATA% | C:\ProgramData |
DebugとReleaseの違い
Releaseの方がコードサイズが小さくなります。
C#のDebug/Releaseコンパイルはどう違うの?
Debug
- 条件付きコンパイルの定数:DEBUG,TRACE
- コードの最適化:ON
- デバッグ情報:FULL
Release
- 条件付きコンパイルの定数:TRACE
- コードの最適化:OFF
- デバッグ情報:pdb-only
初回起動が遅い
「エンド・ユーザーは、0.5秒のフリーズでストレスを感じ、3秒のフリーズはバグだと思う」。昔、冗談半分に言ってみた言葉だが、回りの反応を見るに、割とみな思っていることらしい。
https://atmarkit.itmedia.co.jp/ait/articles/1109/30/news126.html
.NetFrameworkアプリケーションを初回読み込みから速くするには? - MSDNフォーラム
別の.NETアプリケーションが既に動作していれば起動は速いがPC起動時など遅い。
理由は、.NET Framework 自体のロードをファイルシステム・キャッシュ上に乗せるためで「コールド スタート」と呼ばれる、別の.NETアプリケーションが既に動作していると「ウォーム スタート」となる。
ウォーム スタートは、主要なCLRコンポーネント用のページの殆どが既にメモリに読み込まれているときに発生し、貴重なディスクアクセス時間が節約されます。このため、マネージ アプリケーションを再度実行すると、初回よりも短い時間で起動します。
アプリケーションの起動時間
コールドスタートアップはIOバウンドだから当然ngenでは速くならない。2度目以降の起動時間が短くなるのは、OSが一度読んだブロックをメモリにキャッシュしているから。
起動を速くするににプリコンパイルする「Ngen.exe」を使用する方法がある。インストール時にカスタムアクションでNgen.exeでプリコンパイルするといった手法もある。
チュートリアル : カスタム動作を使用して、インストール中にアセンブリをプリコンパイルする
但しプリコンパイルの効果は永続的ではなく、.NET Frameworkなどのバージョンが変わったりなどの条件によって効果が消えてしまう。
.NET 4.5以降では、NgenがWindowsサービスとして動いている(Auto-Ngen)
基本的に、.NETランタイムは、管理対象アプリケーションの使用ログを生成します。システムがアイドル状態の場合、自動メンテナンスタスクがバックグラウンドで実行され、ネイティブイメージが生成されます。これにより、開発者はNGenを明示的に扱う必要がなくなります。※但し、GACアセンブリのみ
※.NET 5以降(旧.NET Core)では、GACの概念は存在しなくなる。
.NET 5の重大な変更点を歴史的テクノロジの面から見る
他にも64bit OS上だとJITのパフォーマンスが悪くなるとの報告がある。x86で作成すると良いらしい。
アプリ起動に限ればクアントアプリは今のところx86ターゲットのほうが良いのか?
※.NET Framework4.6以上の 64ビットモードから.NET環境に最適化されたJITコンパイラ「RyuJIT」で動作するようになり速くなった。
Windows上で電子署名されたロードモジュールを実行すると10秒以上起動にかかることがあるとのことで、対処方法としてアプリケーション構成設定で「generatePublisherEvidence」を「False」に設定する。
Windows上で電子署名されたロードモジュールを実行するとなーんか遅い?という話
Windows10では「高速スタートアップ」機能があり、パソコンの起動を速くするためシャットダウン時にメモリやCPUなどの状態を保存しておくようになっている。これにより初回の初回起動以外は速くなる。
その他
アセンブリの厳密名と特定バージョンについて
厳密名について
厳密名とはVisual Studioなどでアセンブリファイルの参照プロパティで「厳密な名前」と記載されている項目になります。
プロパティで「True」となっているアセンブリファイルは厳密名を設定されています。
基本的にMicrosoftやOracleといった企業が配布しているファイル、バージョンを縛りたい場合に設定されます。
厳密名の構成について
厳密名は以下の4要素によって構成されています。
要素名 |
---|
ファイル名(拡張子無し) |
バージョン番号 |
カルチャID |
公開キートークン |
参照URL:
https://msdn.microsoft.com/ja-jp/library/wd40t7ad(v=vs.110).aspx
http://d.hatena.ne.jp/tekk/20110326/1301133863
厳密名による特定バージョンの縛りについて
特定バージョンについては厳密名と同じで、アセンブリファイルの参照プロパティで確認できます。
特定バージョンを設定するためには、以下の2つの条件を満たす必要があります。
- 参照するアセンブリファイルに厳密名が設定されている。
- 参照するアセンブリファイルがGACに登録済み
特定バージョンがTrueの場合、参照設定しているアセンブリのバージョンが一致しないとコンパイル時にエラーや警告が発生します。
ClickOnceの発行
オフラインの必須コンポーネント
ブートストラップファイルの場所
VS2008 | C:\Program Files (x86)\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages |
---|---|
VS2010 | C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages |
VS2013 | C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\Bootstrapper\Packages |
VS2015 | C:\Program Files (x86)\Microsoft Visual Studio 14.0\SDK\Bootstrapper\Packages |
VS2017 | C:\Program Files (x86)\Microsoft SDKs\ClickOnce Bootstrapper\Packages |
バージョン管理
ClickOnceでは、アセンブリバージョンで設定ファイル(user.cofig)が作成されるので、アセンブリバージョンを変更してしまうと、前バージョンの設定を引き継げません。ってことが発覚!
ClickOnceを使う場合は、発行バージョンで管理するってことになります。
よって、アセンブリバージョンとファイルバージョンは1.0.0.0のままにしておく。
既にインスール済みでインスールできない
ユーザーのアプリケーションデータフォルダに何らかの不具合原因となるファイルが残っているのが原因なので、「C:\Users\<ユーザ名>\AppData\Local\Apps\」以下のフォルダの削除を行う。
ClickOnceでの再インストールでエラー発生
ClickOnceのダウンロード先フォルダのクリアバッチ
アンインストール後に再度インスールしようとした場合、ClickOnceのエラー詳細にて既にインスール済みと判断される。
Setupがゴミ箱にある場合でも、既にインスール済み扱いになってしまうので、対応としてゴミ箱から削除する。
Mage.exeによりクリアする方法
上よりスマートな方法として、オンライン・キャッシュ領域をクリアする
ClickOnceオンライン・キャッシュ領域をクリアするには?
Mage -cc
Chromeでは拡張機能が必要
ChromeでClickOnceを動作させるには、下記のどちらかの拡張機能が必要となる。
デジタル証明書のタイムスタンプ
Done Adding Additional Store
SignTool Error: The specified timestamp server either could not be reached or returned an invalid response.
“timestamp.globalsign.com/scripts/timstamp.dll”は、もう古い。新しい所有者であるDigiCertは移行させよ。
https://stackoverflow.com/questions/9714798/http-timestamp-verisign-com-scripts-timstamp-dll-not-available
%cur%signtool.exe sign /fd sha256 -f %cur%test.pfx -t http://timestamp.globalsign.com/scripts/timstamp.dll setup.exe ↓ %cur%signtool.exe sign /fd sha256 -f %cur%test.pfx -tr http://timestamp.digicert.com?alg=sha256 setup.exe
クラッシュする場合
.NET4.0以降はメモリアクセス違反「AccessViolationException」等になるとアプリケーションが終了する。
.NET Framework 4 以降で挙動が変更されたことにはそれなりに理由があります。というのも、すでにメモリアクセス違反が発生してしまったものを復旧しつつ挙動させることは極めて困難だということです。保証できない状態になっているのを無視してアプリケーションを継続してしまう場合がほとんどなので、それぐらいならアプリケーションをクラッシュさせる方がよほどマシとの考えでしょう。中途半端になって 2 次災害を引き起こすよりも突然の死を選ぶ方が安全である、と。
AccessViolationExceptionを捕捉できるようにする
構成ファイル (*.config) に <legacyCorruptedStateExceptionsPolicy> 要素を入れることで解決できます。
- app.config
<configuration> <runtime> <legacyCorruptedStateExceptionsPolicy enabled="true" /> </runtime> </configuration>
Windows 10の.NET Frameworkインストール対応
- .NET Framework 4.6が標準インストール
- .NET Framework 1.1は手動でインストール可能
- .NET Framework 2.0~3.5は標準ではインストールされていない。
Windowsコンポーネントで.NET Framework 3.5(.NET 2.0 および 3.0 を含む)で有効にする必要がある。
オフライン上なら自動ダウンロードでインストールは容易に出来る。
オフライン環境の場合、Windows 10メディアが必要とのこと
未確認であるが、グループポリシーエディターの変更と代替ソース指定によりメディア不要でインストールが可能
https://teratail.com/questions/177835
.NET Framework 3.5が必要な場合、.NETアプリケーション起動時に下記の確認ダイアログ画面が表示される。
高DPI対応
WinForm
高DPI対応するために、app.manifest ファイルを追加して、dpiAwareをtrueに設定する。
manifest ファイルの配布は不要。
アプリの高DPI(High DPI)対応について 第3回 ~ マニフェストでアプリのDPI対応レベルを変更する ~
「dpiAware」の設定を「true」または「true/PM」または「per monitor」に設定する。
違いは下記参照(※「true/pm」と「per monitor」は同じ意味)
[C#][VB.NET]Windows Formアプリケーションで表示がぼやけるのを防ぐ
- app.manifest
<?xml version="1.0" encoding="utf-8"?> <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1"> <application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware> </windowsSettings> </application> </assembly>
ClickOnceアプリケーションの場合
ClickOnce用のマニフェストファイルとバッティングするのか、dpiAware=Trueの属性を既存のapplication.manifestに追加するとプログラムのダウンロードエラーが発生します。
ClickOnceアプリケーションの高DPI対応方法について
Windows APIで対応する。
- Program.cs
[System.Runtime.InteropServices.DllImport("user32.dll")] private static extern bool SetProcessDPIAware(); [STAThread] static void Main() { if (Environment.OSVersion.Version.Major >= 6) SetProcessDPIAware(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);
WPF
- app.manifest.xml
<application xmlns="urn:schemas-microsoft-com:asm.v3"> <windowsSettings> <!-- Per Monitor V1 [OS >= Windows 8.1] Values: False, True, Per-monitor, True/PM --> <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings"> true/PM</dpiAware> <!-- Per Monitor V1 [OS >= Windows 10 Anniversary Update (1607, 10.0.14393, Redstone 1)] Values: Unaware, System, PerMonitor --> <!-- Per Monitor V2 [OS >= Windows 10 Creators Update (1703, 10.0.15063, Redstone 2)] Value: PerMonitorV2 --> <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings"> PerMonitorV2, PerMonitor</dpiAwareness> </windowsSettings> </application>
Tips
staticクラス
クラス自体を static と宣言することで、インスタンス作成を禁止し、static 宣言したクラスのインスタンスが複数作成できないようにできます。
- staticクラスは継承元として使えず、ほかのクラスが継承することもできません。
- プロパティのセットはメソッドの記述が必要
複数選択のコンボボックス
標準のコンボボックスでは複数選択はできない。よってカスタムコントロールを作成しないと実現できない。
どちらも C# で作成されている。