none
c#で経度緯度をセットできる関数は在りませんか?

    質問

  • こんにちは、掲題の通りWindowsのC#にて経度緯度をセットできるAPIを知りませんか?

    F12開発ツールからだと、エミュレーション→位置情報から経度緯度をエミュレートできるの
    ですが、C#はちょっと探しても見つからないようです。

    Windows.Devices.Geolocation.GeoPositionクラスのCoordinate.Latitude/Longitudeに
    値は入っているのですが、ReadOnlyとなっており、値のセットが出来ないようです。

    ご存知の方は教えて下さい。
    よろしくお願いします。


    2018年1月31日 5:52

すべての返信

  • にっきーさん、こんにちは。フォーラム オペレーターの立花です。
    MSDN フォーラムへご投稿いただきありがとうございます。

    ひとつ確認ですが、YAHOO! JAPAN 知恵袋にも同じ投稿をされてますでしょうか。

    複数のフォーラムに同じ投稿をすると情報が分散してしまったり、
    回答者の方が折角調査して回答したのにすでに解決済みだった、
    などの状況となってしまいますので、どちらかに絞られることを
    ご検討いただけないでしょうか。

    c#で経度緯度をセットできる関数は在りませんか?
    https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q11185421226
    ※別の方の投稿でしたら大変すいません、読み流してください。


    参考になった投稿には回答としてマークの設定にご協力ください
    MSDN/TechNet Community Support 立花楓

    2018年1月31日 6:23
    モデレータ
  • 私はこの問題の解決を大変急いでいます。
    お客様はエミュレータで出来るんだから、APIで出来て当然位に思っています。

    知恵袋の方は、その回答にある通り、方向違いの解決策を提示してくるので
    しょうがないので、こちらに投げました。

    勿論、知恵袋の期限以内にこちらで解決した場合は、知恵袋の方の質問は
    削除します。

    残るのは正確な解決策が提示された方となります。
    よろしくお願いいたします。


    2018年1月31日 6:37
  • にっきーさん、立花です。早速ご返信くださいましてありがとうございます。
    エンド ユーザーから指摘されており大変お急ぎのとのこと承知いたしました。

    何か情報があれば参加者の皆様から投稿があると思いますのでお待ちください。

    また、すでにご検討いただいたとは思うのですが、状況を推察いたしますと、
    サポート サービスにお問い合わせいただいた方がよいかもしれません。
    念のため URL を記載させていただきます。

    サポートサービス契約のご紹介:http://www.microsoft.com/ja-jp/services/support.aspx

    マイクロソフトへのお問い合わせ:(有償のサポートを含みます)
    https://support.microsoft.com/ContactUs

    フォーラムでご質問頂くにあたっての注意点 - 業務上のクリティカルなトラブル等について、より抜粋
    https://social.technet.microsoft.com/Forums/ja-JP/ca9ecfb7-4407-4fcb-b8bd-207d68257e68/


    参考になった投稿には回答としてマークの設定にご協力ください
    MSDN/TechNet Community Support 立花楓

    2018年1月31日 6:55
    モデレータ
  • こちらは1インシデントあたりの価格はどれ位になりますか?
    ざっくりと、今回の案件を解決するのに、どれくらいかかりますか?

    因みに、その方はこんな例を出してきました。

    https://crowdworks.jp/public/jobs/832896
    ※要するに1万円で出来るでしょ?という事です。

    よろしくお願いいたします。
    2018年1月31日 7:22
  • 因みに、私は今回の件は「Geolocation」クラス定義が根源だと思っています。
     ↓

    namespace Windows.Devices.Geolocation
    {
        [ContractVersion(typeof(UniversalApiContract), 65536)]
        [DualApiPartition(version = 167772160)]
        [MarshalingBehavior(MarshalingType.Agile)]
        public sealed class Geocoordinate : IGeocoordinate, IGeocoordinateWithPositionData, IGeocoordinateWithPoint, IGeocoordinateWithPositionSourceTimestamp
        {
            public double Accuracy { get; }
            public double? Altitude { get; }
            public double? AltitudeAccuracy { get; }
            public double? Heading { get; }
            public double Latitude { get; }
            public double Longitude { get; }
            public double? Speed { get; }
            public DateTimeOffset Timestamp { get; }
            public Geopoint Point { get; }
            public PositionSource PositionSource { get; }
            public GeocoordinateSatelliteData SatelliteData { get; }
            public DateTimeOffset? PositionSourceTimestamp { get; }
        }
    }

    F12エミュレータで経度緯度が設定できるのに、何でAPIは"set"が付いてないの…?と。

    2018年1月31日 7:37
  • F12エミュレータで経度緯度が設定できるのに、何でAPIは"set"が付いてないの…?と。
    推測にすぎませんが、多分IEは緯度経度を取得する独自関数を用意しており、「エミュレータで設定されている場合はその値を返し、そうでなければOSから値を取得してくる」という実装にしてるんじゃないですかね。
    2018年1月31日 7:42
  • にっきーさん、立花です。ご返信くださいましてありがとうございます。

    サポート契約についてはサポート契約センターにどの契約で対応できるか含め、
    ご確認いただくのがよいと思います。

    プロフェッショナル サポートについてはこちらに価格表がありました。

    プロフェッショナル サポート
    https://www.microsoft.com/ja-jp/services/professional.aspx#supportprice


    参考になった投稿には回答としてマークの設定にご協力ください
    MSDN/TechNet Community Support 立花楓

    2018年1月31日 7:46
    モデレータ
  • ではエミュレータはどんなAPIを使ってIEに経度緯度を設定しているのでしょうか?
    それがC#から呼び出せれば問題ありません。


    2018年1月31日 7:49
  • F12 開発ツールって何ですか?IEやEdgeでのことですか?
    そうだとすると、開発ツールが取得した正確な位置情報を、開発ツール内で偽って、ブラウザ上で動くプログラムへ渡すのは、簡単ですよね。
    今から作るアプリ限定でいいなら、正確な値か、偽りの値かを振り分ける関数を間に挟めばOK。全アプリに対して偽るのは、事情が変わってきます。

    Jitta@わんくま同盟

    2018年1月31日 7:51
  • ちょっとまた、方向性が…。

    「開発ツールが取得した正確な位置情報を、開発ツール内で偽って、ブラウザ上で動くプログラムへ渡すのは、簡単」
    …何が簡単だと言っているのかちょっと分かりません。

    申し訳ありませんが、C#からフォームアプリを作成し、そこにWebBrowserコントロールのみを
    配置した状態で、経度緯度をセットする手法を提示して頂けませんか?

    よろしくお願いします。
    2018年1月31日 8:18
  • サポート対応の範囲Q&A
    https://www.microsoft.com/ja-jp/services/professional/supportqa.aspx#qa04

    【デバッグ支援、コード レビュー、サンプルコード提供】
    弊社公開情報 (KB、TechNet、MSDN などの弊社 Web サイトを含む) のご紹介までを範囲として対応します。お客様の開発要件にあわせたサンプル コードの提示については、プレミア サポートにて承ります。


    範囲にないのは明らかなので、これはプレミアムサポートになります、という事でしょうか。
    そうであればそちらの価格もご提示お願いしてよろしいでしょうか?
    2018年1月31日 8:24
  • プレミアサポートは年間契約です。

    なお、プレミアサポートはLaborと呼ばれる時間単位での請求ですので、質問者が効率よく尋ねないと費用はうなぎ上りです♪

    残念なことにサポート時間は17:30までとなっていますのでもう時間外になってしまいました。

    2018年1月31日 8:42
  • JavaScriptで作られたプログラムは、ブラウザが動かしています。ブラウザ内に仕込まれたツールが、ブラウザに依頼されたことを偽って報告するように、ブラウザのメーカーが、ブラウザおよびツールを作りこむのは、簡単ですよね。
    やりたいことが「位置情報をセットしたい」しか書かれていませんが、そのニーズの元になったニーズは何ですか。佐祐理さんが「効率よく尋ねないと」と書かれていますが、今の質問は効率が悪いですよ。急ぐなら余計に、聞きたい事に至る背景もまとめて説明しましょう。聞きたい事が不可能でも、「こうすればできるのでは」の道筋が間違っていたら(そして今回は間違っている)、間違っているところから訂正してもらえますから。
    で、JavaScriptで、直接APIに尋ねるのではなく、「GPS情報を参照するクラス」を作り、アプリはこれからGPS情報をもらうようにします。あとは、GPS情報を参照するクラスが、何かの設定によって本物の値を返したり、偽の情報を返すようにすればいいですよね。いや、テスト時にはフツーに使う手法なんだけどなぁ。ウェブアプリで、C#、つまりサーバー側のことなら、クライアントさえ必要ないですよね??まぁ、全体がわからないので、想定があっていなければ無効だけど。

    「1万円でできるでしょ」って、1万円でできるようになるまでに相当の時間=金がかかるってことを理解してもらえないんですよね、悲しいことに。

    Jitta@わんくま同盟

    2018年1月31日 9:19
  • なんでそんなことをしたいのでしょうかね?

    1. 自分で作ったアプリケーション内で位置情報を偽装したい
    2. 自分が作ったアプリケーションではないアプリケーションが取得する位置情報を偽装したい

    どっちのことをやろうとしているんです?

    1なら取得した値をを無視して、任意に置き換えるだけです。
    2ならドライバを書く必要があるでしょう。

    流れは「GPSハードウェア->ドライバ->OSのセンサ取得機能->OSはCOMのAPIで複数のユーザーアプリケーションに対して同時に公開」しかありません。
    ですからハードウェアかドライバを用意しない限りセンサ値は読み込んでくれませんし、ユーザー側から任意のセンサの値を勝手に書き換えるようなことはできません。
    センサー値は複数のアプリケーションが同時に読み出しできます。
    もしも勝手に書き換えができてしまったら重要なセンサー値を読み取っているアプリケーションが致命的が誤動作をすることになるでしょうし、別アカウントでも同時に読み出している場合に権限を越えて書き換えできることになってしまいます。

    ですから方法としては仮想ドライバを用意して、そのドライバに対してユーザーアプリケーションが値の書き換えを要求できるように作るしかありえません。

    まぁ、そんなことを言ってもドライバを作るのは敷居が高いので、こんな方法ですでにある仮想GPSドライバのGPSDirectというソフトを拾ってきて、このソフトのアクセスするシリアルポートに対してcom0comなどのような仮想シリアルポート経由でGPSデータを流し込んでやればもしかしたら偽装できるかもね。


    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2018年1月31日 10:00
  • >ですから方法としては仮想ドライバを用意して、そのドライバに対してユーザーアプリケーションが値の書き換えを要求できるように作るしかありえません。
    >

    本当にそこまでしなければ実現できませんか?
    .NETのフォームブラウザからは隠されていますが、内部的にGPSからの位置情報取得は
    GeoLocator/GeoPosition/Geocoordinate辺りのAPIを使っている可能性は高いと思います。

    そうであれば、単にフォームブラウザを多少拡張して、GeoXXXを見えるようにし、
    GeoLocatorの拡張クラスを作って

    public double Latitude { get; set; }
    public double Longitude { get; set; }

    とすれば仕事は終わりです。後は.Navigate直前に適当な経度緯度をいれれば良いと。
    OSレベルでセットするのは最終手段としたい所です。


    2018年1月31日 12:23
  • そうであれば、単にフォームブラウザを多少拡張して

    .NET の Web ブラウザーは自力で実装しておらず、COM 経由で IE を呼び出しているだけです。
    継承するなどによって拡張できる代物ではありません。

    参考
    http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/WebBrowser.cs,3013ded900e5031e

    -----

    ちなみに、プレミアサポートは最低契約時間が 150 時間ぐらいあって、時間単価が 2 ~ 3 万するので、数百万単位の初期投資が前提になるはずです。

    プロフェッショナルサポートで「公開情報の紹介まで」というくだりはあるので、「IE のコンポーネントを使った際に開発者ツールを自作アプリで提供するための公開情報は存在するか?」みたいなことを聞いて、「ない」と Microsoft からのエビデンス(証拠・文書)が得られたら、それを元に顧客を説得するという道もあると思いますが。

    2018年1月31日 14:05
    モデレータ
  • なんとなく開発の参考になればという投稿です。(うまくいかないサイト、HTMLがあるかもしれませんが、デバッグしていってみてください。)

    JavaScript の参照先位置情報データ(数値)を書き換えるのは恐らく無理ぽいので、JavaScript の geolocation.getCurrentPosition 関数を上書きして、参照先を変えてみることで実現できるかもしれません。

    C# コード
    using mshtml; // Microsoft.mshtml の参照が必要
    using System;
    using System.IO;
    using System.Windows.Forms;
    
    namespace WindowsFormsApp5
    {
        public partial class Form1 : Form
        {
            public Location loc;
    
            public Form1()
            {
                InitializeComponent();
                loc = new Location();
                loc.latitude = 35.683823; 
                loc.longitude = 139.753815;
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                webBrowser1.Url = new Uri(String.Format("file:///{0}/test.html", Directory.GetCurrentDirectory()));
            }
    
            private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
            {
                webBrowser1.ObjectForScripting = loc;
                HtmlElement head = webBrowser1.Document.GetElementsByTagName("head")[0];
                HtmlElement script = webBrowser1.Document.CreateElement("script");
                IHTMLScriptElement domelement = (IHTMLScriptElement)script.DomElement;
                domelement.text =
                    @"function overridegeo() {
                        if (typeof navigator.geolocation == ""undefined"") {
                            navigator.geolocation = new Object();
                        }
                        navigator.geolocation.getCurrentPosition = function(success,failure){success({coords:{latitude:window.external.latitude,longitude:window.external.longitude},timestamp:Date.now()})};
                    };";
                head.AppendChild(script);
                webBrowser1.Document.InvokeScript("overridegeo");
            }
        }
    
        [System.Runtime.InteropServices.ComVisibleAttribute(true)]
        public class Location
        {
            public double latitude { get; set; }
            public double longitude { get; set; }
        }
    }


    HTMLコード
    <!doctype html>
    <html>
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="content-language" content="ja">
    </head>
    <body>
        <button onclick="getcurrent()">現在位置を表示</button>
        <div id="out"></div>
        <script type="text/javascript">
            function getcurrent() {
                var output = document.getElementById("out");
                if (!navigator.geolocation) {
                    output.innerHTML = "<p>Geolocation API がサポートされていません。</p>";
                    return;
                }
                function success(position) {
                    var latitude = position.coords.latitude;
                    var longitude = position.coords.longitude;
                    output.innerHTML = '<p>緯度 = ' + latitude + '° <br>経度 = ' + longitude + '°</p>';
                    var img = new Image();
                    img.src = "https://maps.googleapis.com/maps/api/staticmap?center=" + latitude + "," + longitude + "&zoom=13&size=300x300&sensor=false";
                    output.appendChild(img);
                };
                function error() {
                    output.innerHTML = "";
                };
                output.innerHTML = "<p>読み込み中...</p>";
                navigator.geolocation.getCurrentPosition(success, error);
            }
        </script>
    </body>
    </html>
    2018年2月2日 7:07
  • window.external.latitude/window.external.longiutude
    が使われる過程はどうなっているのでしょう?
    2018年2月2日 13:53
  • 初音と申します。

    上記のJavaScriptの例では、本来、GPSなどで値を出力するだけの関数を直接使わず

    ・GPSから値が取得できたときはその値を返却する

    ・任意の緯度経度が欲しいときは、GPSの値の有無にかかわらず、設定した値を返却する

    という動きをする関数をつくっておき、それをアプリから呼び出しています。

    F12開発者ツールはそういった書き換えもできるのでF12開発者ツールでできているのも同じような仕組みです。

    では、C#で作ったアプリではどうするかですが、Windows.Devices.Geolocation.GeoPositionクラスのCoordinate.Latitude/Longitudeクラスからの値をアプリで直接使わずに、好きな緯度経度を返すようなそんな機能をC#を使ってアプリの中に実装してしまえばいいのです。例えば、緯度経度をCSVファイルとかで1行1秒で読み込むようにしておいて、それを使って動くようにコードを書いてください。
    そのファイルがないときはGeolocationの値を使うとか工夫するとさらに使いやすくなるかもしれませんね。

    今回の話、「お客様はエミュレータで出来るんだから、APIで出来て当然位に思っています。」という点が最大の勘違いですね。

    エミュレーターは開発時に使うもので、だからこそ、わざわざ出かけていかなくても緯度経度を指定してテストができるように緯度経度を測定するハードの代わりに開発者が緯度経度を指定できるように工夫しています。

    同じことを実機でやるのであればAPIがというレベルではなく、実機についているGPSユニットを殺して、そのかわりに任意の緯度経度を流し込むようなハードと置き換えてあげる必要があります。そこまで必要なのであればそうすればいいでしょう。でも、今回のやりたいことは「アプリ自体に任意の緯度経度を設定する機能を付ける」という用件で十分解決できるんじゃないかって思います。


    http://blogs.wankuma.com/hatsune/

    2018年2月3日 13:32
  • https://msdn.microsoft.com/ja-jp/library/a0746166(v=vs.110).aspx

    上記サイトは参考になりますでしょうか?WebBrower のスクリプト内で window.external オブジェクトを使用することで、C# 側のパブリック プロパティにアクセスしたり、メソッドを呼び出せたりします。

    2018年2月4日 17:07