Visual Studioの設定ファイル
Visual Studioの設定ファイルは2つの場所に保存されています。
CurrentSettings.vssettings
1つ目は CurrentSettings.vssettings です。
中はXML形式になっています。
VisualStudioの [ツール → オプション] から [環境 → 設定のインポートとエクスポート] で保存先を確認できます。
また、VisualStudioの ツール に [設定のインポートとエクスポート] のウイザードがあります。
Visual Studioの環境を移動させたいときに便利です。
プライベートレジストリ
2つ目はプライベートレジストリです。
以下の場所に保存されており、レジストリエディターより[ハイブの読み込み]で読み書きできます。
%LOCALAPPDATA%\Microsoft\VisualStudio\[VSバージョン]\privateregistry.bin
※ アンロードして開放しておかないとVisualStudioが起動できなくなるので注意
拡張機能を作っていると ShellSettingsManager がよく出てきますが、このプライベートレジストリに対して読み書きしているようです。
Microsoft.VisualStudio.Shell.Settings.ShellSettingsManager
ShellSettingsManager Class (Microsoft.VisualStudio.Shell.Settings) | Microsoft Learn
Git fatal: unsafe repository ('xxxxxxxxx' is owned by someone else)
fatal: unsafe repository ('xxxxxxxxx' is owned by someone else)
git v2.35.2 でセキュリティアップデートが入ったようで、コミットが開けなくなりました。
gitの対象フォルダの所有者が自分では無いことが原因のようで、まずはフォルダの所有者を確認しましょう。
どうしても所有者が自分以外になってしまう場合は、safe.directoryの設定をして例外的に許可を出せば大丈夫です。
バージョン管理システム「Git」にセキュリティ上の脆弱性、Git for Windowsユーザーやマルチユーザー環境利用者が取るべき対処法は? - GIGAZINE
いきなりgitが使えなくなった - 2022(山崎はるかのメモ)
TortoiseGitで「fatal: unsafe repository」なエラー - Qiita
事の発端:
VisualStudio内のGitが開けなくなって困った
→ SourceTreeでは開ける (内蔵Gitのためバージョンが低い)
→ VisualStudioのGitのバージョンがわからんぞ
↓ここにあるっぽい VisualStudioも内蔵Gitでした…
VisualStudio 2017だとGitのエラー表示してくれるけど、VS2019だと「エラーが1つあります」しかなくて困った困った
ソリューションを.Net Frameworから.NETへバージョンアップする方法
.NET5からソリューションの記述方法が変わりました。
今までのソリューションを.NET5、.NET6にするには結構めんどくさかったり。。。
マイクロソフトから「.NET アップグレード アシスタント」としてツールが出ています。
インストール
// インストール dotnet tool install -g upgrade-assistant // アップデート dotnet tool update -g upgrade-assistant
使い方:
upgrade-assistant upgrade <MySolution.sln> または upgrade-assistant upgrade <MyProject.csproj>
後は英語の説明で動かしていけばコンバート完了です。
WPF アプリを .NET 6 にアップグレードする - .NET Core | Microsoft Docs
.NET アップグレード アシスタントを利用して .NET Framework から .NET 5 に超簡単アップグレード 【Windows Forms】 - Qiita
[WPF] 編集可能なComboBoxのTextが消える問題
編集可能なComboBox (IsEditable="True")のItemsSorceを変更したときに、ItemsSorceから現在の項目が消えた場合にTextも消滅してしまう問題です。
あくまでもComboBoxのメニュー(DropDown)は「選択もできるよ!」のつもりなのに、メニューから消えるとTextも消えてしまいます。
<ComboBox IsEditable="True" ItemsSorce="{Binding Items}" Text="{Binding Item}" />
class vm { public string Item { get; set; } public IEnumerable<string> Items { get; set; } = new []{ "みかん", "りんご", "ぶどう" }; }
例えば ItemsSorce :[みかん、りんご、ぶどう] 、 Text:[みかん] の状態で、
ItemsSorce を [りんご、ぶどう] に変更すると Text が空欄になってしまうわけです。
イベント的にSelectionChangedしか無いのでこんな感じで対応しました。
public IEnumerable ItemsSource { get; set; } void OnSelectionChanged( object sender, SelectionChangedEventArgs e ) { var comboBox = (ComboBox)sender; if( this.ItemsSource != comboBox.ItemsSource ) { this.ItemsSource = comboBox.ItemsSource; if( comboBox.SelectedItem == null ) { var text = comboBox.Text; comboBox.Dispatcher.BeginInvoke( (Action)( () => { comboBox.Text = text; } ) ); } } }
comboBox.Dispatcher.BeginInvoke がミソで、一旦comboBox.Textは空欄になってしまいますが再度入力し直す動きなります。
SelectedItemは先にNullになるけど、Textはまだ残っている不思議
参考:
ikriv.com
.Net 5 でIntelliSenseやツールチップを日本語にする
Visual Studio 2019を使い始めました。
というか.Net 5 を使い始めました。
.Net 5の初期状態だとツールチップが英語です😥
.Net Framework 4.5のときも同じような状態でしたが、これはバグだったみたい。
Visual StudioのIntelliSenseが英語になっていたので日本語に戻した - tmegos blog
c# - Visual Studio 2015 ツールチップ(summary)の日本語化 - スタック・オーバーフロー
.NET Framework 4.5でIntelliSenseのツールチップが英語になる理由 - The Grimoire of Nonsense
.Net 5(.NET Core 3.0以降)ではそもそも初期状態は英語のようです。
日本語化
日本語化する手順は公式でしっかり書かれていました。
ただ、インストールする場所(jaフォルダを配置する場所)がよくわからなくて苦労しました。
docs.microsoft.com
日本語のインテリセンスファイルをダウンロード以下のサイトよりダウンロードします。
dotnet.microsoft.com
解凍したフォルダの各jaフォルダを規定の位置にコピーします。
初期インストール場所は「%ProgramFiles%\dotnet\packs」なので、
例えば「Microsoft.WindowsDesktop.App.Ref」だと
C:\Program Files\dotnet\packs\Microsoft.WindowsDesktop.App.Ref\5.0.0\ref\net5.0
の中にjaフォルダをコピーしてください。
Microsoft.NETCore.App.Ref のほうも同じように
C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\5.0.0\ref\net5.0
の中にjaフォルダをコピーしてください。
ただ、NETStandard.Library.Ref には 5.0.0 がないんだけど、使わないから必要ないかな?
日本語化できました!
他の設定はデフォルトのままでした。
VisualStudioを起動している場合は、再起動が必要です。
参考サイト:
Visual Studio 2019 での .NET Core のインテリセンスを日本語化する - Alternative Architecture DOJO
[Visual Studio 2019] ソリューションエクスプローラーでAltキードラッグで、リンクファイルが作成できない
Visual Studio 2019で、リンクファイルのショートカット操作が消されてしまったようです。
https://social.msdn.microsoft.com/Forums/en-US/66715ed6-ed1b-4922-be5c-d79d3f3c22b8/altdrag-to-create-a-link-to-a-file?forum=visualstudiogeneral
https://developercommunity.visualstudio.com/t/ctrl-shift-drag-and-altdrag-could-not-add-the-exis/760536
そろそろ 2019 移行するかと思ったらしっかり踏んだ
DLL化して参照しろってことかな・・・
WPFでWindows Runtime API の Windows.winmd について
WPFでWindows 8、8.1、10 のAPIを呼ぶことができます。
デスクトップ アプリからのWinRT API利用 | ++C++; // 未確認飛行 C ブログ
WPFのプロジェクトで Windows.winmd を参照するとライブラリとして使えるようになります。
WPF などの .NET Framework のアプリから UWP の API を呼ぶ - かずきのBlog@hatena
WPFアプリ(.Net Framework)でUWPのAPIを使う - Qiita
Windows SDKのインストール場所は C:\Program Files (x86)\Windows Kits\ になります。
Windows 8、8.1 はいいのですが、Windows 10 になるとメジャーアップデート毎にSDKのバージョンが違うため気をつける必要があります。
(ここからの部分を書きたいだけ)
Windows 10 のSDKをインストールすると C:\Program Files (x86)\Windows Kits\10\ にインストールされます。
Windows 10 SDK (10.0.10240) ~ (10.0.15063.468) (1507~1703)では Windows.winmd が同じ場所にインストールされてしまうので注意です。
最後にインストールしたSDKの Windows.winmd が上書きされるようで、
Windows.winmd の違いはファイルの見た目では分からないので、どのバージョンのファイルか分からなくなります。
Windows 10 SDK (10.0.16299.91) (1709) からそれぞれのバージョンでフォルダ分けされるようになったのでこの問題は解決しています。
(ここまで)
まあ、Win10のサポート期間があるので、サポート対象のバージョンを使えばよさそうです。
ついでに、、、
特定のバージョンしか対応していませんが、NuGet から追加できるようになったようです。
こっちを使ったほうが簡単ですね。
.NET のプロジェクトから WinRT API を呼ぶのが凄く簡単になってます - かずきのBlog@hatena
MSDN コードギャラリーの提供終了
MSDN コードギャラリーのページが無くなり、新しいコードサンプルページが作成されています。
https://code.msdn.microsoft.com/
MSDN コード ギャラリーの提供終了 | Microsoft Docs
新しいコードサンプルページ
Browse code samples | Microsoft Docs
悲しいことに参考になるサンプルのリンクが消滅している状態です。
- 10 行でズバリ !! シリーズ
- 連載! とことん シリーズ
などなど
今までのページはGitHubに保存されているので、この中から探しましょう!
Microsoft Archive · GitHub
https://github.com/microsoftarchive/msdn-code-gallery-community-0-9-non-alphabetic
https://github.com/microsoftarchive/msdn-code-gallery-microsoft
https://github.com/microsoftarchive/msdn-code-gallery-community-a-c
https://github.com/microsoftarchive/msdn-code-gallery-community-d-l
https://github.com/microsoftarchive/msdn-code-gallery-community-m-r
https://github.com/microsoftarchive/msdn-code-gallery-community-s-z
[WPF] Expression Blend ライブラリのいらない言語リソースファイルたち
Expression Blend の Behavior 便利ですよね!
すっごいよく使います。
System.Windows.Interactivity.dll Microsoft.Expression.Interactions.dll
Visual Studioから使うExpression BlendのBehavior達 - かずきのBlog@hatena
参照設定で追加してー
ビルドするとー
なにこれいらない・・・
こんな感じの謎のフォルダーができちゃいます。
de en es fr it ja ko ru zh-Hans zh-Hant
理由は簡単 System.Windows.Interactivity.dll、Microsoft.Expression.Interactions.dll の言語リソース用のファイルです。
皆さん大体こう思いますね。
日本語しか使わないんだけど!?
ていうかいらないんだけど!?
削除したり、そもそもコピーされないようにしたりすることで回避しているようです。
[C#] ビルド後イベントで不要なxmlや言語フォルダを削除する - ざこノート
c# - When compiling WPF application language folders are copied to build folder - Stack Overflow
コピーされないようにする
大本から削除してコピーされないようにするパターンを紹介します。
コピー元になるファイルたちは以下の場所にインストールされます。
.netのバージョンによって v4.0 と v4.5 があるようです。
C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.0\Libraries C:\Program Files (x86)\Microsoft SDKs\Expression\Blend\.NETFramework\v4.5\Libraries
削除するのは戻せなくなるので、新しいフォルダに移動させていまいました。
これでビルド時に不要な言語ファイルがコピーされなくなります。
特にエラーも発生しないのでおすすめです。
Visual Studio Version Selector がぶっ壊れた
Visual Studioのソリューションファイル.slnはVisual Studio Version Selectorが関連付けられています。
Visual Studio Version Selectorは.slnファイル内に記載されているVisual Studioのバージョンを読み取り、適切なVisual Studioのバージョンを起動します。
調子が悪いとこんな画面が開きます
選択も何も、空っぽなんですが!?
OKを押しても反応がなく、キャンセルを押すと「開けませんでした。」とエラーウインドウが出る始末
新しいバージョンのVisual Studioをインストールしようとしたらこうなりました。。。
原因はVisual Studioの変更や更新が途中で止まっていることのようで、
Visual Studio Installer で止まっている変更や更新を進めたら正しくVisual Studioが起動しました。
最悪は修復すれば直るようです?
参考:
How do I add versions to “Visual Studio Version Selector”, my list is empty - Stack Overflow
ExceptionのHResultについて
C#でファイル操作などのWindowsに関わる操作を行うと内部的にはWindows APIが呼ばれます。
WindowsAPIはC#ではないので、エラーになったときにはC++的な形でエラーコードを返します。
それをC#でラッピングしてあるので、C#でExceptionとしてエラーを取得する事ができます。
C#のExceptionのメッセージだと大まかな分け方しかしていないので詳細に知りたい場合はHResultの値を調べます。
try{ }catch(Exception e ){ e.HResult // <- こいつについての話 }
例えばファイルを置換に失敗した場合 IOException になります。
try{ System.IO.File.Replace(sourceFileName, destFileName, null); }catch( IOException e ){ // e.Message → 置換されるファイルを削除できません。 // e.HResult → -2147023721 }
int型の表示でマイナスの値が表示されますが、所詮ビットデータなので2進数表示で確認します。
更に上位下位として半分ずつにします。
2進数:1000000000000111 0000010010010111 16進数:0x8007 0x0497
で、これがなんなんだっていうと 上位の0x8007はWin32エラーコードということを示しています。
下位の0x0497がエラーの番号です。
ERROR_UNABLE_TO_REMOVE_REPLACED 1175 (0x497)
置換されたファイルを削除できませんでした。置換されるファイルと置換ファイルの名前は、元のまま変更されていません。
ReplaceFileA function | Microsoft Docs
こんな感じでWindows APIのエラーコードにたどり着くことができます。
無理やりワンライナー
こんな感じのときってあると思います。
var result = ""; if( 条件1 ){ result = "1つ目"; }else if( 条件2 ){ result = "2つ目"; }
この初期化めんどくさくない?
var result = "";
メソッド
メソッドに切り出したいけど、メソッド名考えるの大変なんだよなー
var result = GetResult( 条件 ); string GetResult( 条件 ){ if( 条件1 ){ return "1つ目"; }else if( 条件2 ){ return "2つ目"; } return ""; }
匿名メソッド&即実行
Func
var result = ( (Func<string>)( () => { return "1"; }) )();
または
var result = ( new Func<string>( ()=>{ return "2"; }) )();
()括弧多すぎ問題
そしてStaticへ・・・
そしてこうなった・・・
var result = Func.Run( ()=>{ return "1"; } ); public static class Func { public static T Run<T>( Func<T> func ) { return func(); } }
他の便利な使い方
初期化のときにメソッドの形で書けます。
public class Item { public string Value { get; set; } = Func.Run( () => { return ""; } ); }
初期化のときにメソッドの形で書けます。その2
var item = new Item(){ Value = Func.Run( () => { return ""; } ), }
[Rx] 変更通知の合成はObservable.Merge<object>です。
WPFでBindingする時にLivetを使っていたのですが、ReactivePropertyが面白そうだったのではじめました。
Livetだと自分の好きなタイミングで変更通知イベントを出せていたのですが、Rxだとそのタイミングもロジックとして書く必要があります。
要は、AプロパティとBプロパティのどちらかが変わった時に、Cプロパティの変更通知を出したい みたいな
Livet
Livet で書くとこんな感じ
public class LivetViewModel : ViewModel { public int A { get => _A; set { if( _A != value ){ _A = value; this.RaisePropertyChanged(); this.RaisePropertyChanged( nameof(this.C) ); } } } int _A; public int B { get => _B; set { if( _B != value ){ _B = value; this.RaisePropertyChanged(); this.RaisePropertyChanged( nameof(this.C) ); } } } int _B; // A, B が変わった時にCの値が変わる public int C => A + B; }
ReactiveProperty
だいたいCombineLatestを使えと書いてあるのでこんな感じ
public class RxViewModel { public RxViewModel() { this.C = this.A.CombineLatest(this.B, (a,b)=> a+b).ToReactiveProperty(); } public ReactiveProperty<int> A { get; } = new ReactiveProperty<int>(); public ReactiveProperty<int> B { get; } = new ReactiveProperty<int>(); public ReactiveProperty<int> C { get; } }
ReadOnlyとかSlimとかしっかり使うとこんな感じ
public class RxViewModel2 { public RxViewModel2() { this.C = this.A.CombineLatest(this.B, (a,b)=> a+b).ToReadOnlyReactivePropertySlim(); } public ReactivePropertySlim<int> A { get; } = new ReactivePropertySlim<int>(); public ReactivePropertySlim<int> B { get; } = new ReactivePropertySlim<int>(); public ReadOnlyReactivePropertySlim<int> C { get; } }
ただし、CombineLatest だと全ての値がそろわないと通知が始まらないので「値がない場合~」とかはできません。
やっと本題 Observable.Merge<object> を使いましょう。
public class RxMerge { public RxMerge() { this.C = Observable.Merge( this.A, this.B ) .Select(x => this.A.Value + this.B.Value ).ToReadOnlyReactivePropertySlim(); } public ReactivePropertySlim<int> A { get; } = new ReactivePropertySlim<int>(); public ReactivePropertySlim<int> B { get; } = new ReactivePropertySlim<int>(); public ReadOnlyReactivePropertySlim<int> C { get; } }
CombineLatest の謎のラムダ式 (a,b)=> a+b も消えてスッキリしました。
全ての型が同じ場合は型推論でジェネリックの<T>部分を書かなくていいですが、複数の型が混ざる場合は<object>とすれば問題ありません。
そしてそして、本当にやりたかったことは ReactiveCommand のコマンドが実行可能かどうかという CanExecute 部分の書き方なのだった・・・
Observable.Merge<object>( // 変更通知 が来たら条件判定したいReactiveProperty this.A, this.B ).Select( x => { // True になる条件 return this.A.Value != 0 && this.B.Value != 0; } ) .ToReactiveCommand()
複数の条件が複雑に混ざり合うような時にとても重宝します。
追記 2018/10/18
ジェネリックのキャストの都合上IObservable<[struct]>がIObservable<object>にキャストできないので無理やり変換します。
こんなの用意して
public static Observable { public static IObservable<object> Cast<T>( this IObservable<T> source ) where T: struct { return source.Select( x => (object)x ); } }
こうだ!
public class RxMerge { public RxMerge() { this.C = Observable.Merge( this.A.Cast(), this.B ) .Select(x => this.A.Value + int.Parse( this.B.Value ) ).ToReadOnlyReactivePropertySlim(); } public ReactivePropertySlim<int> NumItem { get; } = new ReactivePropertySlim<int>(); public ReactivePropertySlim<string> StrItem { get; } = new ReactivePropertySlim<string>(); public ReadOnlyReactivePropertySlim<int> C { get; } }
2019/01/29 追記
ToUnit() で IObservable
いまさら聞けないReactive Extensions.3 - Qiita
Unit は戻り値なしのvoid的なやつだそうです。
でもデバッグ的にはIObservable<object> のほうが便利だなー
// ReactiveProperty.dll namespace Reactive.Bindings.Extensions { public static class ToUnitObservableExtensions { public static IObservable<Unit> ToUnit<T>( this IObservable<T> self ); } } // こんな感じ Observable.Merge( this.A.ToUnit(), this.B.ToUnit() )
[WPF] タッチ長押しで右クリックをやめる(□を表示させない)
少ないですがWindowsタブレット用のアプリでドラッグやタッチしっぱなしの操作がメインのときにタッチ長押しの右クリック機能が邪魔なときがあります。
対象のXamlの添付プロパティにこれを使いするだけ
Stylus.IsPressAndHoldEnabled = false
こんな感じです。
<Grid Stylus.IsPressAndHoldEnabled="False"> </Grid>
WindowsFormsではこの設定はなさそうなので珍しくWPFの利点でしょうか
参考
[C#/VB/XAML] WPF 4 における TouchDown や TouchUp など基本的なイベントを使用して、マルチタッチ対応アプリケーションを作成 in C#, VB.NET
他にもStylusクラスには面白そうなものがあるのでご覧あれ
Stylus Class (System.Windows.Input) | Microsoft Docs
[WPF] ComboBoxをItemsSourceとSelectedItemで扱う時の注意
2019/06/13 再度試してみたら問題なく初期値が設定されました
SelectedItem で初期値を設定する場合には SelectedItem を先に設定してから ItemsSource を変更しないと初期値が設定されない場合があるようです。
味気ないので、雰囲気コード(実際には動かない)置いておきます。
こんなコンボボックスを作って
<ComboBox ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}" DisplayMemberPath="Name" />
ViewModel部分
public class ViewModel : INotifyPropertyChanged { public List<Item> Items { get; set; } // 変更通知 public Item SelectedItem { get; set; } // 変更通知 public void ChangeComboBox(){ // これだとダメ //this.Items = new List<Item>(){ // new Item(){ Name = "1" }, // new Item(){ Name = "2" }, // new Item(){ Name = "3" }, // }; //this.SelectedItem = this.Items.First(); var items = new List<Item>(){ new Item(){ Name = "1" }, new Item(){ Name = "2" }, new Item(){ Name = "3" }, }; this.SelectedItem = items.First(); this.Items = items; } } public class Item { public string Name { get; set; } public int Value { get; set; } }