Category: C#

Visual Studio 2015 で独自言語に対応させてみる。


みむらです。
新年初めての記事ですかね。明けましておめでとうございます。

一年の計は元旦にありということで、元旦から大幅に過ぎてしまいましたが
書き初めを。


何をするか、ということですが
タイトルにあるとおり「独自言語に対応させてみよう」ということで。

2016-01-16 (1)

たとえばこういう感じのが30分ほどで作成できます。


とはいえ、こんなことをしようとする人は、
たぶん放っておいても大丈夫そうな皆さんしかいなさそうな気もしますので、さくっとポイントのみ。

 

まず、作るためには “MPF for Projects” というのを使用するのが楽ちんなのですが、
Visual Studio 2015 用が出ていないようでしたので適当に作って公開しました。

https://github.com/mimura1133/uo_mpfproj14

この中にある “Samples/UsagiProject” の中身を見ると、大体の作り方が見えてくるかと思います。


1. とりあえず、新しい言語プロジェクトを作る:

CustomProjectPackage.cs を開くと、
このようにプロジェクト名とプロジェクトファイルの拡張子を指定できますので、
ここを適当にごにょごにょ。

image

次に上記でごにょごにょした形に合うように、 Templates フォルダ内を設定します。

Projects の中に作ったプロジェクトファイルとアイコンが、
新規作成時のプロジェクト一覧に並びます。

image

デフォルトのままですと、こんな感じですね。

image

 

重要な点として、このとき “Template” フォルダの中身について
ビルドアクションを “コンテンツ” そして “Include in VSIX” を “True” にする
必要があります。

これを忘れると、プロジェクト一覧に出てこなくなります。

image

 


2. 作ったはいいけれど、コンポーネントが読み込めないとかのエラーが出る。

主に、 “Microsoft.VisualStudio.Project” が読み込めないエラーだと思います。

デバッグ中に例外が出て、読み込みが無視されている場合は再ビルドで治る事がありますが、
それでも治らない場合。

extension.vsixmanifest および source.extension.vsixmanifest の “資産” のところに、
”MefComponent” として自身が登録されているか
どうかを確認してみてください。

image

私もこれで2時間潰しました orz.

 


あともう一つ。

ソリューションのファイル群が置いてある場所までのパスに日本語が
入っていないかどうか。

vsix に閉じ込めるファイルやソースのファイルは日本語でも問題なさそうなのですが、
そのソリューション一式のファイルまでのパス中に日本語が入っていると、
インストールしても何も出てこない vsix ファイルが生まれます。

たぶん vsixmanifest の処理あたりで問題が起きていそうな気がしますが、
詳しい所はよく分かりません。。


3.F5 でデバッグしたい!

まず、自身の参照のところに

Microsoft.VisualStudio.Modeling.SDK.Integration.14.0

を入れておきます。
次に、プロジェクトのプロパティより、「デバッグ」の「外部プログラムの開始」に

C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\devenv.exe

と記述し、コマンドライン引数に

/rootsuffix Exp

と書くといい感じに F5 でデバッグできるようになります。


 


そんなこんなで、色々と楽しい事が出来そうな Visual Studio さん。

image

Visual Studio 2015 の vsixmanifest を見ると、
このように Express 版に対してもインストール設定ができるようなので
私のようなフリーソフト作者にとっては、わざわざお高いソフトを導入してもらわなくても試してもらえるってことで、とてもわくてかです。

 

そんなこんなで、私の書き初めは今年も C# から。
それではみなさん Happy Visual Studio Life を。

No Visual Studio, No…. いや、 VS なくても頑張れるかな・・

C# で ini ファイルの内容を任意のクラスに格納するコードを書いてみた。


どうもみむらです。

C# で ini ファイルを操作するとなると、
よくあるのが GetPrivateProfileString あたりを叩いて取得することになります。

でもその場合、いちいち要素を指定して取得しなければならず、
特に複数のキー(フィールド)がある場合に複数回コードを書くのも面倒です。

特に ini ファイルの項目が多くて、こんな状態になった日には・・。

image

 

・・ということで、 Reflection を使用して
この辺をすごく楽に出来るような感じでコードを書いてみました。

 

コード:

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;

public static class Ini
{
    [DllImport("KERNEL32.DLL")]
    public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, uint nSize, string lpFileName);

    [DllImport("KERNEL32.DLL")]
    public static extern uint GetPrivateProfileInt(string lpAppName, string lpKeyName, int nDefault, string lpFileName);

    [DllImport("KERNEL32.DLL")]
    public static extern uint WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);

    public static T Read<T>(string section, string filepath)
    {
        T ret = (T)Activator.CreateInstance(typeof(T));

        foreach (var n in typeof(T).GetFields())
        {
            if (n.FieldType == typeof(int))
            {
                n.SetValue(ret, (int)GetPrivateProfileInt(section, n.Name, 0, Path.GetFullPath(filepath)));
            }
            else if (n.FieldType == typeof(uint))
            {
                n.SetValue(ret, GetPrivateProfileInt(section, n.Name, 0, Path.GetFullPath(filepath)));
            }
            else
            {
                var sb = new StringBuilder(1024);
                GetPrivateProfileString(section, n.Name, "", sb, (uint)sb.Capacity, Path.GetFullPath(filepath));
                n.SetValue(ret, sb.ToString());
            }
        };

        return ret;
    }

    public static void Write<T>(string secion, T data, string filepath)
    {
        foreach (var n in typeof(T).GetFields())
        {
            WritePrivateProfileString(secion, n.Name, n.GetValue(data).ToString(), Path.GetFullPath(filepath));
        };
    }
}

 

使い方:

ini ファイルの読み取りたいセクションに合わせたクラスを用意します。

    public class Human
    {
        public string name;
        public int age;
    }

でもって次のような ini ファイルを用意して

[01]
name=TARO
age=20

あとはこんな風に呼び出します。

        static void Main(string[] args)
        {
            var h = Ini.Read<Human>("01", "DATA.INI");

            h.age = 15;
            h.name = "JIRO";
            Ini.Write("02", h, "DATA.INI");
        }

 

実行しますと、

image

こんな感じでデータが読み出されます。

でもって、 ini ファイルは

[01]
name=TARO
age=20
[02]
name=JIRO
age=15

こんな感じに、ちゃんとセクション 02 が書き込まれます。


躓きそうなところ:

データを格納するクラスが、こういう感じに {get; set;} な状態になっている場合:

    public class Human
    {
        public string name { get; set; }
        public int age { get; set; }
    }

上記コード内の GetFields を GetProperties に換え、 FieldType を PropertyType に変えれば動作します。


・・そんなわけで、もし良ければ自己責任でご利用ください-。

Visual Studio 2010 から 2012 のヘルプを見に行くようにする。


新年明けましておめでとうございます。みむらです。

・・あけおめ関連の記事は後で書くとしまして、
大掃除中に見つけたことで一つ。

 

現在私の環境には、Visual Studio 2010 と 2012 がインストールされており、
それぞれを使い分けています。

ただヘルプに関しては、両方インストールしておいても特に幸せなことはありませんので
ディスクを圧迫する関係から、いつか一つにまとめたいと思っていました。

今回、
Visual Studio 2010 から Visual Studio 2012 のヘルプを参照するようにして、
問題解決(?)しましたので紹介します。

 

環境:

Windows 8 Pro
Visual Studio 2010 Ultimate
Visual Studio 2012 Ultimate


1. Visual Studio 2010 をインストール。

2. Visual Studio 2012 をインストール。

3. Visual Studio 2012 のヘルプビューアにコンテンツをインストールする。

image

 

4. Microsoft Help Viewer 1.1 とその Language Pack をアンインストール

image

消す際には、 Language Pack から消すとよさそうです。

 


5.  ms-xhelp:// を Help Viewer 2.0 で処理するように関連づける。

http://mimumimu.net/software/blogup/vs2010_hv2.zip

ftype や assoc でできないかとやってみたのですがどうもうまくいきませんでしたので、
レジストリファイルを用意しました。

このファイルを展開して結合します。


手順は以上のようになります。

当方の環境で試しましたところ、ソースコード上の命令に対する F1 ヘルプも動作しました。
(挙動がわからない命令にキャレットを合わせて F1 を押す)

 

複数環境を入れてある方は、このような方法で統合して、
リアル空間だけではなく、バーチャル空間の掃除も済ませてみてはいかがでしょうか。

Launcher.LaunchUriAsync でブラウザが立ち上がらない。


みむらです。
填まりましたのでメモ。

 

現象:

Launcher.LaunchUriAsync(
	new Uri("http://mimumimu.net")
	);

こういうコード書いてもブラウザが立ち上がらない。

 

確認ポイント:

マニフェストの「機能」のうち、
「プライベートネットワーク(クライアントとサーバ)」が有効になっているかどうか。

 

どうもこいつが有効じゃないと、立ち上がらないようで。

Win8 で通信回線の種別を判定する。(できるとおもう


みむらです。これは完全にメモ書き。
・・・検証環境がないので実験できていませんが(ぉぃ

 

環境:

Windows 8
.net Framework 4.5

 

要求:

・インターネットにつながってる
・容量制限や従量課金の回線じゃないことを判定する。

 

コード:

                var profile = NetworkInformation.GetInternetConnectionProfile();
                if (profile != null)
                {
                    if (profile.GetNetworkConnectivityLevel() == NetworkConnectivityLevel.InternetAccess
                        && profile.GetConnectionCost().NetworkCostType == NetworkCostType.Unrestricted)
                    {
                        // ほげほげ
                    }

                }

 

やっぱり、回線を気にして通信させたいよね、とふと。
あとで組み込もう。