C#
ちょっとやりたくなったのですが、意外と出てこなかったので記載。
拡張で remove comment で検索して出てくる拡張機能を入れる。
コマンドパレットでremove all comment
これでまるっと消せる。
Billion laughs攻撃っていうのがある。
XMLで参照を多重に定義して、メモリを食いつぶさせてPCとかアプリを固まらさせるやつ。
で、これってSVGでも可能だったんですね。
下の画像をFireFoxで見るとFireFoxのタブが固まる。(Chromeは大丈夫だった)
https://github.com/cirosantilli/web/blob/master/svg-billion-laughs.svg
上の画像をDLして、例えばパワーポイントとかに画像挿入しようとするとパワポも固まる。
上の画像のソースを見ればわかりますが、この程度の参照の組み方だけで、
組み合わせ爆発でヤバイ事になるという訳なんですが、
参照をネストさせるようなものはやっぱり考え物って事ですね。
正規表現なんかも、例えば
(a|b|c)(e|d|f)
みたいに組み合わせで色々やるとエライこっちゃになるパターンがあったと思う。
↑だけじゃ再現させられなかったんですが、昔どこかのコードで見たんだよなー。
組み合わせ爆発って怖いですね。結構意識せずにやっちゃいそうな気もする。
正規表現でいうとMSDNの正規表現のベストプラクティスのページがすごく面白かった。
長さが 5 文字を超えると、文字列の文字が 1 文字増えるたびに処理時間が約 2 倍に増加します。 つまり、有効に近い文字列の長さが 28 文字になると処理に 1 時間以上かかり、33 文字になるとほぼ 1 日かかることになります。
確かに正規表現作ってる時って、正しい文字列ばっかり考慮してるきらいがありますよね。
「*」とか「+」とかのネストとかもやばそう。
正規表現だと楽ーとか早いとかいう話は良く見聞きしますが、
やっぱり一概にそうも言えないですよね。
すごいはまった。
こんな感じで、JSONデータをPOSTするリクエスト。
string url = @"http://localhost/****"; using (var client = new HttpClient()) { HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url); request.Content = new StringContent(@"{***}", Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); var restext = await response.Content.ReadAsStringAsync(); Console.WriteLine(restext); }
そしたら、結果が↓になる。サーバはApache。
502 Proxy Error
リバースプロキシでバックエンドに飛ばしてるんですが、
Apacheのログをdebugレベルにしてログを見ると、
# access.log "POST /hogeurl HTTP/1.1" 502 341 "- - - - - 202 Keep-Alive" # error.log [proxy_http:error] [pid 14412:tid 1408] (20014)Internal error (specific information not available): [client ::1:50107] AH01102: error reading status line from remote server 127.0.0.1:3002 [proxy_http:debug] [pid 14412:tid 1408] mod_proxy_http.c(1311): [client ::1:50107] AH01105: NOT Closing connection to client although reading from backend server 127.0.0.1:3002 failed. [proxy:error] [pid 14412:tid 1408] [client ::1:50107] AH00898: Error reading from remote server returned by /hogeurl
みたいな感じ。何もわからん。
アプリ側のログには何も書かれてないのでそもそも、アプリまで到達してないっぽい。
普通のGetはちゃんと行くし、PostManで同じPOST投げてもちゃんと上手くいく。
という事は、きっと変なヘッダがついてるんだろうと。
で、C#って発行するリクエストの最終的なHeaderってどうやって見ればいいんですかね?
Apache側でログの指定ってヘッダのキー指定で一つ一つ見るしかなさそうなので、
変なヘッダ入ってないか確認するのが出来ないのですが・・・。
良いやり方ないもんか。。。
まーいいや。結論から言うと、C#のHTTPClientで発行するPOSTにはデフォで↓がつくっぽい。
Expect: 100-Continue
拡張ヘッダという事みたいですが、これが悪さしてるっぽい。というかApacheと相性悪い?
これを送らないようにするために、↓にする。
string url = @"http://localhost/****"; using (var client = new HttpClient()) { ServicePointManager.Expect100Continue = false;//これ!! HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, url); request.Content = new StringContent(@"{***}", Encoding.UTF8, "application/json"); var response = await client.SendAsync(request); var restext = await response.Content.ReadAsStringAsync(); Console.WriteLine(restext); }
もーね・・・。って感じ。
以下、上に行きつくまでに試した事。
まず、プロキシがおかしいのかとApacheでプロキシまわりのエラーが起きたときに
とりあえずやってみる設定は↓。
# httpd.conf SetEnv force-proxy-request-1.0 1 SetEnv proxy-nokeepalive 1
そしたら、↓を返すようになった。
417 Expectation Failed
そのほか、POSTManで指定してるヘッダ入れてみたり色々してみて、
この417から「Expect: 100-Continue」に行き着いた感じ。
何かこー、アレな感じですね。。。
最近、どこからか.netMVCをCloneしてビルドすると↓のエラーが出た。
'bin\roslyn\csc.exe' パスの一部が見つかりませんでした
で、これが出たら↓
パッケージマネージャコンソール(ツール⇒Nugetあたり) update-package Microsoft.CodeDom.Providers.DotNetCompilerPlatform -r
csc自体はc#のコンパイラだったと思うんだけど、これが見つからないってこと?
ちょっとなぞ。
むかーしむかし、IEのDLLホスティングっていうのがありまして、
そん時に確か、何かのDLL使おうとした時にcsc.exeがねーってエラーが出た記憶があるなー。
だから何だって話ですけど。
参考サイト↓
大した話じゃないんですが、下記ソース。
public void hoge() { //プリミティブ int t = 1; int tt = t; Console.WriteLine("ref={0}", Object.ReferenceEquals(t, tt));//⇒False //オブジェクト Object o = new object(); Object oo = o; Console.WriteLine("ref={0}", Object.ReferenceEquals(o, oo));//⇒True //string string s = "s"; string ss = s; Console.WriteLine("ref={0}", Object.ReferenceEquals(s, ss));//⇒True //オブジェクトの中のプリミティブ SampleValue x = new SampleValue(); SampleValue xx = x; Console.WriteLine("ref={0}", Object.ReferenceEquals(x, xx));//⇒True Console.WriteLine("ref={0}", Object.ReferenceEquals(x.v, xx.v));//⇒False!!! } public class SampleValue { public int v = 1; }
オブジェクトは参照渡しだから、ReferenceEqualsがTrueになるのは分かるんだけど、
中のプリミティブな奴ってFalseになるんですね。
そうなのかーーーと思って。
なんか、すんませんでした。。。
Googleトレンドで遊んでて、最近の言語はどんな感じなのかなって見てた。だいぶ偏見によった検索ワードですが、下記。
意外だったのがPythonがJava抜いてるじゃんってとこ。ついにJavaも終焉か・・・って事にはならないと思いますが、私的にはJavaは10年後にレガシーとか言われてそうな気がしている。
昔はPythonとかニッチ(死語?)な言語だと思ってましたが、割と来てるんだね。
最近どうなのか気になったので、StackOverFlowのアンケート結果(2018)を確認してみた。
アンケートの前提
回答:100,000人
地域的なとこ↓
インドとアメリカとヨーロッパが多そう?
仕事柄↓
フロントエンド・バックエンド・フルスタックがほとんどだけど、正直SEなんて、よっぽど特化してなければ、ほぼ3つのどれかにあてはまるよね。。。
あと、回答者のうち半分くらいは5年未満の経験者(仕事として)って事みたい。
若めの回答者が多いっていう認識でよろしいのかな?
良く使う言語
良く使うフレームワーク
JavaScriptを一番使うらしい。まー、今はほぼWeb系でしょうし。フロントエンドの人はそうなるでしょうね。フレームワークもJavaScript寄りのものが順当に上位。
個人的には.net Coreが割と上位に来てて意外だった。Spring抜いてんだね。C#好きとしてはなんかうれしい。VS2003あたりの.net(正確にはVisualStudio)はクソだと思ったけど、2008あたりから急激に良くなりましたよね。MSがOSSに寄ってきた感じがちょっとした。
まー、C#はVisualStudioありきの言語なのは否めませんが、それでも気持ちよく書けるのが素晴らしいと思う。半分はVSが良いって感じかもかも。
あと、Pythonもやっぱ来てるんだね。ほぼ機械学習・AI・データマイニング絡みだと思いますが、Pythonも書きやすくて好き。
今後数年はPythonとC#がバックエンド的には来るのかしらね。フロントエンドはJavaScript一択でしょうけど。
使ってるDB
あれ、SQLServerって上位なん?Oracleってどうしたの?MariaDBには頑張ってほしい。期待上げ。PostgreSQLも上位にあがってるのね。つか、DBランキングとちょっと違う感じがする。↓DBランキング。
Oracleって実際どうなんでしょうね。あと、MongoDBはジワジワ来てますな。何系で使われてるんだろ。業務システムって基本RDB使うと思うから、Webサービス的なやつで使ってんのかしら?スキーマレスなDBは業務システム的なデータ構造でガチガチのシステムは微妙な気がするしの。検索のパフォーマンスとかもろもろ。IDで抜くとかだけならMongoの方がパフォーマンスは良さそうなのかしら。いちをNo検証でイメージだけで書いてますので。。。
必要な言語
Python大人気すな。AI・機械学習まわりでしょうけども。3年後にはどうなっているかしらね。
使ってるIDE
VisualStudioCodeつよ。とゆーか自分もVSCode使ってますね。何か、軽くて使い勝手がよい。ただ、2年前かな?もっと前?に出たばっかで細かいツールというかプラグインが揃いきってないかもかも。でも十分。
所感
やっとJavaは終わったね。.netには頑張ってほしい。C#好き。
で、Pythonがひとまず伸びそうな感じ?今使ってる最中だから人が増えて便利なライブラリとかツールとか増えるとうれしい。まー自分で作れって話ですけど。
意外にもDBはMongoDBが来てるのね。多少は来ると思ってたけど、こんなに来てるとは思ってなかった。Webサービス的なシステムには向いてるのかな。業務システムではちょっと厳しそうな気がする。とりあえずロックが割とゆるかった記憶が。。。
まー、日本で仕事してる身としては、そもそもアンケートに日本からの回答があまり入ってないので世界的にはそんな感じかーという程度。日本てガラパゴスってよく言われるじゃない。世界的な基準のアンケートだと身の回りには割と当てはまらなかったりするしね。
参考サイト
この前、Rを外部から実行するっていうの書いたけど、C#から呼ぶためのライブラリが普通にあったので、書き直し。探し方が悪かったかしらね。。。
R.Netっていうのを使う。NuGetからインスコ。「R.NET.Community」っていうのもあるんだけど、何が違うんだろうか?リンク先とかも一緒なんだけど。。。あー、もちろん使う場合は端末にR本体がインストールされてる必要あり。
そしたらとりあえず、呼び出しサンプル。
using RDotNet; static void Main(string[] args) { REngine.SetEnvironmentVariables();//これは省略可。 using (REngine engine = REngine.GetInstance()) { engine.Evaluate("sample.data <- iris"); engine.Evaluate("str(sample.data)"); } Console.WriteLine("おしまい"); Console.ReadLine(); }
↑は呼び方的には公式のチュートリアルのまま。
まず、32bitか64bitでビルド変えないとだめかも。64bitでやる場合はプロジェクトのプロパティ⇒ビルドで「32ビットを優先」のチェックを外さないとだめそうですね。あと、使うR.dllのフォルダも設定が必要。さらに、Rのパスを通してない場合は、実行時に環境変数のPATHにRのパスを追加しておいた方が良さげ。で、色々したのが↓。パスを編集するメソッドはさすがのすたっくおーばーふろーがサンプル。
static void Main(string[] args) { string rpath = SetupPath("R-3.4.2");//インストールしたバージョンを指定 REngine.SetEnvironmentVariables(rpath); using (REngine engine = REngine.GetInstance()) { engine.Initialize();//最近はこれがいるらしい engine.AutoPrint = false;//これ付けないと代入してる式で中身が丸ごと出てきてうざい engine.Evaluate("sample.data <- iris"); engine.Evaluate("str(sample.data)"); } Console.WriteLine("おしまい"); Console.ReadLine(); } public static string SetupPath(string Rversion) { string rDllPath = Environment.Is64BitProcess ? string.Format(@"C:\Program Files\R\{0}\bin\x64", Rversion) : string.Format(@"C:\Program Files\R\{0}\bin\i386", Rversion); //DLLのフォルダが無かったら例外 if (!Directory.Exists(rDllPath)) { throw new DirectoryNotFoundException(string.Format("Not found : {0}", rDllPath)); } var newPath = string.Format("{0}{1}{2}", rDllPath, System.IO.Path.PathSeparator, Environment.GetEnvironmentVariable("PATH")); Environment.SetEnvironmentVariable("PATH", newPath); return rDllPath; }
でだ、ここまでやっても何故だか実行時に「Rlapack.dllがありません」みたいなエラーが出る端末が稀にいる。意味が分からん。どう見てもあるんだけどね。。。プローブ?がおかしいのだろうか。そういう時はとりあえず、実行ファイルと同じフォルダに「Rlapack.dll」をRのインストール先からコピーしてあげると動くようになる。なんだろね。
ほいで、あとは色々な呼び出し。
static void Main(string[] args) { string rpath = SetupPath("R-3.4.2"); REngine.SetEnvironmentVariables(rpath); using (REngine engine = REngine.GetInstance()) { engine.Initialize(); engine.AutoPrint = false; //////////////////////////////////////// //arulesでアソシエーション分析 //////////////////////////////////////// //ライブラリの読み込み engine.Evaluate("library(arules)"); //アソシエーション分析 engine.Evaluate("data(\"Adult\")"); engine.Evaluate("rules <- apriori(Adult,parameter=list(minlen=2, maxlen=4, support=0.5, confidence=0.9))"); //結果のサマリー engine.Evaluate("summary(rules)"); //結果の表示 engine.Evaluate("inspect(rules)"); //RのデータフレームをC#で扱えるデータにする var dd = engine.Evaluate("Adult@itemInfo").AsDataFrame(); //つまみ食い Console.WriteLine(dd[1, 1]); //////////////////////////////////////// //kmeansの結果を取得 //////////////////////////////////////// //irisデータ使う(いつものやつ) engine.Evaluate("iriswk <- iris[1:150, 1:4]"); engine.Evaluate("iriswk.km <- kmeans(iriswk, 2)"); engine.Evaluate("iriswk.km"); engine.Evaluate("iriswk.km$cluster"); var kmlist = engine.Evaluate("iriswk.km$cluster").AsNumeric(); //////////////////////////////////////// //Plotの画像をファイルにはく //////////////////////////////////////// var path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName() + ".png"); string Code = @"plot(1:10, pch=1:10, col=1:10, cex=seq(1, 2, length=10))"; engine.Evaluate(string.Format("png('{0}', {1}, {2})", path.Replace('\\', '/'), 420, 420)); engine.Evaluate(Code); engine.Evaluate("dev.off()"); } Console.WriteLine("おしまい"); Console.ReadLine(); }
最近、またMecab使ってるんですが、Mecabはそのまま使うと凄く細かく分解されちゃって結構使いにくい。形態素解析したい文章である程度の単語のまとまりのままにしたい場合はユーザー辞書作るのが手っ取り早い。
C#でNMecab使う場合を想定。NMecabはNugetでインストール。
辞書作るときは、本家のサイトからWindows用をダウンロードしてインスト。
そしたら↓の感じのCSVで登録した単語の一覧を作る。例えば「chacha.csv」っていうファイル名で保存した場合。
ジャスミン茶,,,10,名詞,一般,*,*,*,*,独自辞書,ヨミ,ハツオン ウーロン茶,,,10,名詞,一般,*,*,*,*,独自辞書,ヨミ,ハツオン
フォーマットは↓の感じらしい。自分は原型のところに分かりやすいように自分の辞書っていうのがわかる文字を入れてる。
表層形,左文脈ID,右文脈ID,コスト,品詞,品詞細分類1,品詞細分類2,品詞細分類3,活用形,活用型,原形,読み,発音
そしたら、↓コマンドでコンパイルして辞書ファイルを作る。フォルダはインストールしたフォルダを適当に。
cd C:\Program Files (x86)\MeCab\bin mecab-dict-index -d "C:\Program Files (x86)\MeCab\dic\ipadic" -u "C:\Program Files (x86)\MeCab\dic\userdic\chacha.dic" -f shift-jis -t utf-8 "C:\Program Files (x86)\MeCab\dic\userdic\chacha.csv"
オプションとかは「mecab-dict-index -h」でヘルプ見た方が早い。
で、読み込みのCSVはSJISでいいと思うんだけど、dicファイルの方はUTF8指定しておかないと、プログラム側で読み込むときにエラーになる。。。あと、CSVファイルの最後は改行入れない方がいい。
dicファイルが出来たらプログラム側の適当なフォルダに入れて、↓の感じでMeCabParamを作る。
MeCabParam mPara = new MeCabParam(); //まず、システム辞書があるフォルダの指定 mPara.DicDir = @"C:\*******\dic\ipadic"; //そしたら、ユーザ辞書ファイルを下の感じで指定 List<string> wkList = new List<string>(); //複数指定可 wkList.Add(@"C:\*******dic\userdic\chacha.dic"); //MeCabParamにセット mPara.UserDic = wkList.ToArray();
↑はプログラム内でやってるけど、app.configとかで外だしもできるっぽ。
で、ほぼやりたい感じには上記でなるんだけど、コストの指定とかもう少し理解したいところ。まだ困ってないのは、大した解析やってないからでしょうし。。。
システムの保守とかしてると、サーバのCPUとかメモリとかシステムのプロセスとかディスクの容量とか統計を取りたくなる。WindowsOSの話。パフォーマンスカウンタでいけるみたいな話はありますが、なんか使い勝手が悪いのと裏でずっと動かしてていいのかなんか微妙。あと結果のファイルもなんか微妙。
とゆーわけで自分でサービスを作った話。
パフォーマンスカウンタ使うには、最初にSystem.Managementを参照に追加しないとだめ。そしたら↓の感じで見たいカウンタ(項目)別に設定する。
//using System.Management; //CPUの使用率 PerformanceCounter pc = new PerformanceCounter("Processor", "% Processor Time", "_Total", true); Console.WriteLine(pc.NextValue());
で、どんな指定が出来るのかの一覧があんまない。環境によるってことかしらね。なので、何が使えるのか最初に↓の感じで一覧作ってCSVあたりにはいておく。
//PerformanceCounterCategoryを使う場合は↓のusingが必要 //using System.Diagnostics; public static void ListUpCounters() { using (StreamWriter wr = new StreamWriter(@".\パフォーマンスカウンタ一覧.csv", false, Encoding.GetEncoding(932))) { //カテゴリの一覧 PerformanceCounterCategory[] pccates = PerformanceCounterCategory.GetCategories(); wr.WriteLine(String.Format("カテゴリ,タイプ,オブジェ,単位,説明"));//一覧用ヘッダ foreach (PerformanceCounterCategory tmpcate in pccates) { //カテゴリのオブジェクト名 wr.WriteLine(String.Format("\"{0}\",,,,\"{1}\"", tmpcate.CategoryName, tmpcate.CategoryHelp)); try { //カテゴリのインスタンス一覧を取得 string[] instnames = tmpcate.GetInstanceNames(); //インスタンス名を出力 foreach (string instanceName in instnames) { wr.WriteLine(String.Format("{0},INSTANCE,\"{1}\"", tmpcate.CategoryName, instanceName)); } //カウンタの一覧 PerformanceCounter[] counters; if (instnames.Length > 0) counters = tmpcate.GetCounters(instnames[0]); else counters = tmpcate.GetCounters(); //パフォーマンスカウンタ名を表示 foreach (PerformanceCounter cnt in counters) { wr.WriteLine(String.Format("{0},COUNTER,{1},\"{2}\",\"{3}\"", tmpcate.CategoryName, cnt.CounterName, cnt.CounterType, cnt.CounterHelp)); } } //インスタンス情報なしはInvalidOperationExceptionらしい catch (InvalidOperationException) { wr.WriteLine(String.Format("インスタンス情報なし")); } } } }
動かしたときのプロセスとかスレッドとかも全部出てくるので結構多いかも。。。
基本的にはCPUとメモリとディスクあたりを見る感じかしら。
カテゴリ | カウンタ | インスタンス | 中身 |
---|---|---|---|
Processor | % Processor Time | _Total | CPU使用率(%) |
Memory | Available Bytes | 利用可能メモリ(B) | |
Memory | Pages/sec | ページ数 | |
LogicalDisk | % Free Space | _Total | ディスク全体空率(%) |
LogicalDisk | Free Megabytes | _Total | ディスク全体空容量(MB) |
LogicalDisk | Current Disk Queue Length | _Total | ディスク待ちキュー数 |
インスタンスないやつは指定するときは引数無しで。
あと、カテゴリで「Process」の奴は個別のプロセスのCPU使用率とかも見れる。 インスタンスはプロセスの名前。同じ名前で何個もできる場合は「プロセス名#2」みたいな番号のつけ方される。固定で名称指定は無理だと思うので、↓の感じで、そのカテゴリのインスタンスを全部取って、プロセス名が含まれてたら使うみたいなやり方。
public static void proccessval() { var catelist = PerformanceCounterCategory.GetCategories().ToList(); foreach (PerformanceCounterCategory tmp in catelist.Where(n=>n.CategoryName=="Process")) { try { string[] instnames = tmp.GetInstanceNames(); foreach (string instanceName in instnames) { if (instanceName.Contains("w3wp"))//例えばIIS { PerformanceCounter pc = new PerformanceCounter("Process", "% Processor Time", instanceName, true);//CPU使用率(%) Console.WriteLine(pc.NextValue()); pc = new PerformanceCounter("Process", "Working Set", instanceName, true);//使用メモリ(B) Console.WriteLine(pc.NextValue()); } } } catch { } } }
ディスクについてはドライブ単位に見たい場合も↑と同じノリで出来る。あと、プロセスの場合、そのプロセスのコマンドラインが欲しかったりする場合がある。その場合は↑の奴に↓の感じで追加。
public static void proccessval() { var catelist = PerformanceCounterCategory.GetCategories().ToList(); foreach (PerformanceCounterCategory tmp in catelist.Where(n=>n.CategoryName=="Process")) { try { string[] instnames = tmp.GetInstanceNames(); foreach (string instanceName in instnames) { if (instanceName.Contains("w3wp")) { PerformanceCounter pc = new PerformanceCounter("Process", "% Processor Time", instanceName, true);//CPU使用率(%) Console.WriteLine(pc.NextValue()); pc = new PerformanceCounter("Process", "Working Set", instanceName, true);//使用メモリ(B) Console.WriteLine(pc.NextValue()); //プロセスIDをとってコマンドライン取得する PerformanceCounter tmppc = new PerformanceCounter("Process", "ID Process", instanceName, true); tmppc.NextValue(); Process ps = Process.GetProcessById(Convert.ToInt32(tmppc.NextValue())); string proccessid = Convert.ToInt32(tmppc.NextValue()).ToString(); ManagementClass mc = new ManagementClass(new ManagementPath("Win32_Process")); foreach (ManagementObject obj in mc.GetInstances()) { if (obj["ProcessId"] != null && obj["CommandLine"] != null) { if (obj["ProcessId"].ToString() == proccessid) { string commandline = obj["CommandLine"].ToString(); string proccaption = obj["Caption"].ToString(); } } } } } } catch { } } }
で、あとはこれをWindowsサービスで作って、とりたいカウンタの値を10秒単位とか1分単位とかでログファイルに書くみたいな感じ。
あーあと、毎回新しくカウンタ作るでもいいかもだけど重そう。。。最初に初期化だけして使いまわす場合、最初は存在したプロセスが途中でいなくなったりすると例外で落ちるので、その場合は初期化からまたやり直しみたいなロジック入れないとダメかな。あと途中でプロセス増えた場合もダメなので、定期的に初期化し直すように組まないとだめかしらね。
- .net
- .netMVC
- AlmaLinux
- Apache
- AWS
- bitnami
- BulkCopy
- C#
- CentOS
- centos
- CentOS7
- CentOS8
- CLI3
- ClientVPN
- cookie
- CSS
- D3
- d3
- Django
- DNS
- docker
- docker-compose
- EntityFramework
- file
- GDI+
- Git
- HTML5
- IIS
- image
- inspect
- install
- IVS
- javascript
- JavaScript
- Jest
- JMeter
- JSON
- ldap
- Linux
- linux
- Log
- MariaDB
- MeCab
- MongoDB
- MVC
- mvc
- node.js
- npm
- nuxt
- OpenVPN
- POST
- Postgre
- proxy
- puppeteer
- Python
- python
- R
- Redis
- Redmine
- redmine
- Ruby
- SQLServer
- svg
- this
- Unicode
- UnitTest
- VirtualBox
- Visual
- VisualStudio
- VPN
- VSCode
- vscode
- Vue
- windows
- Windows
- Windows8.1
- エクセル
- エラー
- オブジェクト
- キャッシュバスティング
- コマンド
- コンソール
- サロゲート
- ストアド
- ソート
- トランザクション
- プロキシ
- プログラム
- ラムダ式
- ロードバランサ
- ワードクラウド
- 単体テスト
- 変換
- 外字
- 文字コード
- 日本語化
- 正規表現
- 画像
- 辞書
- 配列