Windows Dev. Site

wxPython

GUIの表示方法はいろいろありますが、今回はwxPythonを試してみました。

参考)https://zetcode.com/wxpython/widgets/
環境)wxpython v4.2.1 / python v3.10.13 / Anaconda Navigator 2.4.0 / Windows 11

wxhello.py

import wx

class Example(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(Example, self).__init__(*args, **kwargs)
        self.InitUI()

    def InitUI(self):
        wx.CallLater(3000, self.ShowMessage)

        pnl = wx.Panel(self)
        btn1 = wx.Button(pnl, label='Close', pos=(20, 20))
        btn1.Bind(wx.EVT_BUTTON, self.OnClose)

        btn2 = wx.Button(pnl, label='Message', pos=(20, 60))
        btn2.Bind(wx.EVT_BUTTON, self.ShowMessage2)

        self.SetSize(550, 250)
        self.SetTitle('Message box')
        self.Centre()

    def ShowMessage(self):
        wx.MessageBox('Hello!', 'Info',
            wx.OK | wx.ICON_INFORMATION)

    def ShowMessage2(self, e):
        wx.MessageBox('Hi!', 'Info',
            wx.OK | wx.ICON_INFORMATION)

    def OnClose(self, e):
        self.Close(True)

def main():
    app = wx.App()
    ex = Example(None)
    ex.Show()
    app.MainLoop()

if __name__ == '__main__':
    main()

実行

python wxhello.py

py03

py04

メッセージ表示関数を二つ用意したのは、呼び出し方によって、引数が違うからです。
メモでした。

Python.NET

今回は、.NET のコードをIronPythonでなくPythonから呼び出しライブラリを使用したサンプルをためしてみました。

参考)https://github.com/pythonnet/pythonnet

環境)pythonnet v3.0.3 / python v3.10.13 / Anaconda Navigator 2.4.0 / Windows 11
hello.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import clr

clr.AddReference("System.Windows.Forms")
import System.Windows.Forms as WinForms
from System.Drawing import Size, Point


class HelloApp(WinForms.Form):

    def __init__(self):
        super().__init__()
        self.Text = "Hello! From Python"
        self.AutoScaleBaseSize = Size(5, 13)
        self.ClientSize = Size(392, 217)
        h = WinForms.SystemInformation.CaptionHeight
        self.MinimumSize = Size(392, (117 + h))

        self.button = WinForms.Button()
        self.button.Location = Point(160, 64)
        self.button.Size = Size(82, 20)
        self.button.TabIndex = 2
        self.button.Text = "Click Me!"

        self.button.Click += self.button_Click

        self.textbox = WinForms.TextBox()
        self.textbox.Text = "Hello!"
        self.textbox.TabIndex = 1
        self.textbox.Size = Size(82, 40)
        self.textbox.Location = Point(160, 24)

        self.AcceptButton = self.button
        self.Controls.Add(self.button)
        self.Controls.Add(self.textbox)

    def button_Click(self, sender, args):
        WinForms.MessageBox.Show(self.textbox.Text)

    def run(self):
        WinForms.Application.Run(self)

def main():
    form = HelloApp()
    app = WinForms.Application
    app.Run(form)

if __name__ == '__main__':
    main()

実行

python hello.py

py02

Windows Form の表示とマウスクリックを確認できました。

IronPython 3.4

このブログは7年ぶりの投稿になります。その間他のブログで書いていましたが、Windowsに関連した内容をふたたびこのブログで書くことにしました。
そのきっかけとなったのは、IronPythonがまだメンテされていることからです。このブログで過去Python関連を多く扱っていることからここに書いた方が良いと思いました。

py00

早速インスツールしてLINQのプログラムを動かしてみました。

py01

ファイルに保存した .pyファイルからのipyコマンド実行でも確認しました。
Ironシリーズの他の言語は、メンテがされていないものもありますが、さすがPythonは用途があるのでしょうね。

参考)https://stackoverflow.com/questions/628482/can-you-use-linq-types-and-extension-methods-in-ironpython

[お知らせ]

このブログを始めて4年が経過しようとしています。
MicrosoftやWindows固有の情報を記事にしてきましたが、Microsoftがオープンソースと幅広く提携する方針を受け、MSテクノロジーに限って記事を書くことにあまり意味を感じなくなってきました。またBizSparkの期限が切れたことにより、材料に制約ができてきたのも要因です。
まだ継続はしていきますが、更新ペースはさらにゆるやかになると思います。

しかしまだまだAzureFunctionのような興味深いものもあり、まだこれから取り上げたいと思っています。(今回時間がないため先送り。他のブログがちょっと忙しいので・・)

em7s

BizSparkがきっかけではじめたこのブログですが、他の技術ブログを書くきっかけにもなり大変有意義でした。

Unity 5 / C#

マルチプラットホーム対応。プログラマを引き付けるある種のキーワードですが、私自身はそれぞれのプラットホームにあった言語を使えばいいと思う派です。なのでXamarinのようにC#でiOSのアプリを作れると聞いてもあまりそそられないのですが、ゲームの統合開発環境のUnityはちょっと違う感じを受けました。ゲームにかぎらず3Dオブジェクトの表現手段としても魅力に思えたからです。この環境がC#を一段と魅力的にしています。(Macにもインストールしました)

ということでUnity5ことはじめとして今回取り上げてみました。

unity01
球と立方体にマテリアルを適用して配置します。立方体の方をプログラムで回転させてみました。(使い方はネット上にたくさんありますので、他のサイトを参考にしてください。)
unity02
コードの編集は、スクリプトをダブルクリックするとすでにインストール済のVisualStudio2013が立ち上がりました。

以下実行画面(立方体が回転します)
unity03

このツール自体、使っているのが楽しいです。(3Dレンダリングツールを使うのは、LightWave以来で15,6年ぶりくらいかも?)
これを使ったAndroidアプリを作ってみたくなってきました。

Bash / Windows

BashがWindowsで走るようになる、というニュースはいろんな意味で衝撃的でした。
その発表からかなりたちましたが、ようやく導入してみました。

WindowsマシンでLinuxを走らせたいというときは、いままでVM、Cygwinなどで代用してきましたが、このBashはかなり使いやすく自然に感じます。(Macか好きなのもコンソールが使えるからです。)

インストールは以下を参考にさせていただきました。
「Bash on Ubuntu on Windowsをインストールしてみよう!」

http://qiita.com/Aruneko/items/c79810b0b015bebf30bb

Anniversary Updateの後、Windows機能の有効化、開発者モードにすることで使えるようになります。
基本はUbuntuです。
定番のApache2とPHP5を試してみました。

sudo apt-get install apache2 php5
sudo service apache2 start

bash01

http://locahost/index.phpでアクセス

bash02
JavaScriptを使ったWebアプリでちょっとしたテストするときに、ローカルにWebサーバを立てたいときがあります。このようなときXAMPPを使っていましたが、これでその必要がなくなります。

bashコマンドで、WindowsのコマンドプロンプトがBashに変身するわけですが、まだ慣れないせいかちょっと違和感があります。(Windowsの一部にまだなりきれていない感が・・)
しかしこれは慣れの問題で、利便性は文句ないですね。

Computer Vision API

OpenCVをちょっと本格的にやってみたくなり、いろいろと調べていたところ、Microsoftの画像の内容を解析するWeb APIがあることを知りました。

https://www.microsoft.com/cognitive-services/en-us/computer-vision-api

まずサイトにあるデモ画像を解析してみました。
cv01

Description { “type”: 0, “captions”: [ { "text": "a beautiful woman standing on a beach", "confidence": 0.679803189466983 } ] }

このように表示されました。写真の内容を解説しています。
次に、名古屋市街の写真をアップしてみました。

cv02
以下、上の画面で表示されていない部分
cv02b

{ “type”: 0, “captions”: [ { "text": "a view of a city street filled with lots of traffic", "confidence": 0.9142464427110745 } ] }

見事に説明されています。
RESTでリクエストするとJSONデータがレスポンスが得られますが、ここではWeb画面だけでテストしました。
すばらしいです!
しかしこんなのは序の口なのでしょうね。今後もっとすごいことになりそうな予感がします。

取得データ

Features:
Feature Name
Value
Description
{ “type”: 0, “captions”: [ { "text": "a view of a city street filled with lots of traffic", "confidence": 0.9146197984849257 } ] }
Tags
[ { "name": "outdoor", "confidence": 0.9992619156837463 }, { "name": "sky", "confidence": 0.9889569878578186 }, { "name": "road", "confidence": 0.9851759672164917 }, { "name": "traffic", "confidence": 0.95611971616745 }, { "name": "street", "confidence": 0.9378244280815124 }, { "name": "way", "confidence": 0.9301115274429321 }, { "name": "scene", "confidence": 0.9083418846130371 }, { "name": "city", "confidence": 0.8684317469596863 }, { "name": "highway", "confidence": 0.5730462670326233 }, { "name": "lined", "confidence": 0.5066318511962891 }, { "name": "long", "confidence": 0.4045528769493103 }, { "name": "busy", "confidence": 0.3945377469062805 } ]
Image Format
jpeg
Image Dimensions
1224 x 1632
Clip Art Type
0 Non-clipart
Line Drawing Type
0 Non-LineDrawing
Black & White Image
False
Is Adult Content
False
Adult Score
0.007880046032369136
Is Racy Content
False
Racy Score
0.013227200135588646
Categories
[ { "name": "outdoor_", "score": 0.00390625 }, { "name": "outdoor_city", "score": 0.21484375 }, { "name": "outdoor_street", "score": 0.24609375 } ]
Faces
[]
Dominant Color Background

Dominant Color Foreground

Dominant Colors

Accent Color

#BA9711

PowerShell / Linux

LinuxやMac用のPowerShellがマイクロソフトからリリースされました。
パイプ処理やリモート機能などLinuxでも使えたら便利と思っていたので、ずっと期待していました。
早速インストールして、試してみました。

環境: Ubuntu 16.04
下記よりUbuntu用をダウンロードして、dkpg -i でパッケージインストール。

https://github.com/PowerShell/PowerShell/releases/tag/v6.0.0-alpha.9

バージョン表示
linuxps01

リモート設定
linuxps02
まだ無理なのでしょうか・・

Apache2のプロセス表示
linuxps03
aliasを見てみると lsにはなにも割り当てられていません。
またおいおい試していきたいです。

PowerShell RunspacePool

パワーシェルコマンドを非同期で並列に実行するテストです。時間を表示して並行に実行していることを確認しました。

環境: PowerShell version 5 / Windows 10

$PSVersionTable
Set-ExecutionPolicy RemoteSigned

(ポリシー変更を管理者権限で実行)

実行画面
powershell_run01

runtest.ps1

$cmds = @(
 "sleep 1; get-date", 
 "sleep 2; get-date", 
 "sleep 3; get-date" 
 )

$len = $cmds.Length
$pool = [RunspaceFactory]::CreateRunspacePool(1, $len)
$pool.Open()
$arrPs  = New-Object System.Collections.ArrayList
$arrRes  = New-Object System.Collections.ArrayList
for ( $i = 0; $i -lt $len; $i++ ) {
	$cmd = $cmds[$i]
	$ps = [PowerShell]::Create()
	$ps.RunspacePool = $pool
	$ps.AddScript($cmd) | Out-Null
	# $ps.AddCommand("Out-String") 
	$res = $ps.BeginInvoke()
	$arrPs.Add($ps) | Out-Null
	$arrRes.Add($res) | Out-Null
}

while ( $arrPs.Count -gt 0 ){
	for ( $i = 0; $i -lt $arrPs.Count; $i++ ){
		$ps = $arrPs[$i]
		$res = $arrRes[$i]
		if($ps -ne $null){
			if($res.IsCompleted){
				$result = $ps.EndInvoke($res)
				Write-host $result
				$ps.Dispose()
				$arrPs.RemoveAt($i)
				$arrRes.RemoveAt($i) 	
			}
		}
	}
}
$pool.Close()

参考: https://www.gmo.jp/report/single/?art_id=195

Bot Framework

最近はやりのBot。マイクロソフトもちょっと前にフレームワークを出しましたが、このBotBuilderを使って、まずは標準入出力で簡単に動かせるものを作ってみました。
環境: node ver 4.4.5 / Windows 10

Nodeは下記からダウンロード

https://nodejs.org/en/download/

node-v4.4.5-x64.msi

インストール

npm init
npm install –save botbuilder
npm install –save restify

Botは入力に対して、何かを返すというのが基本ですが、予想していない入力に対しては’?'で返し、ユーザの名前が登録されていないときは名前を尋ね、以後その名前で語りかけるという仕組みをつくったつもりです。

var builder = require('botbuilder');

var dialog = new builder.CommandDialog();

dialog.matches(["Hi", "Hello"], function (session) {
  if (!session.userData.name) {
    session.beginDialog('/getname');
  }
  else{
    session.send("> Hello, " + session.userData.name + "!");
  }
});
dialog.matches("How are you", function (session) {
  session.send("> I'm fine.")
});
dialog.matches("bye", function(session){
  session.send("> See you.")
  session.endDialog();
});

dialog.onDefault(function (session) {
  if(session.userData.name != session.message.text){
    session.send("> " + session.message.text + "?");
  }
});

var bot = new builder.TextBot();
bot.add('/', dialog);
bot.add('/getname', [
  function(session) {
    builder.Prompts.text(session, "> What's your name?");
  },
  function(session, results) {
    session.userData.name = results.response;
    session.send('> Hi, ' + session.userData.name);
    //session.endDialog();
    session.beginDialog('/');
  }
]);

bot.listenStdin();

実行結果
bot01

/getnameセッションが終わると、/に戻るかと思いましたが、そうならないためまたセッションを再度開始しています。
まだ調査不足のところがありますが、とりあえずここまでメモしておきたいと思います。

参考:

http://qiita.com/o0h/items/1a51cd0bbd9c38027388

http://www.atmarkit.co.jp/ait/articles/1604/15/news032_3.html

Small Basic

プログラムの学習言語として50年以上の歴史を持つBasic言語。私も初めてプログラムを学んだのはこの言語でした。当時家庭で手軽に試せるプログラム言語といえば、Basicくらいしかありませんでしたが、現在は多数の言語があり、それゆえどれから学んだらいいかとても迷います。
しかし時代は進んでもプログラムを楽しんで学ぶという観点かから、まだBasicがよく使われているのを目にします。そのような中マイクロソフトの製品で”Visual Basic”ではなく、”Small Basic”なるものがあったので使ってみました。

ダウンロード: https://www.microsoft.com/ja-jp/download/details.aspx?id=46392
環境: Small Basic 1.2 / Windows 10
smallbasic01
Turtleというオブジェクトが最初からあり、図形を書いたりできます。
このあたりが”Basicらしい”ところで気にいりました。
Scratch等のブロックを並べてプログラムを記述する言語にもありますが、プログラム実行環境自体に、何かを動かす、といったわかりやすい目的があるのが特徴的です。
このプログラムはマウスポインタの位置にTurtleを移動させる簡単なものです。
smallbasic02
プログラムを発行して、Webで共有することも可能です。
smallbasic03
このあたりは今っぽいところてす。
smallbasic04
無料でここまで使えるのは、魅力的です。

Reactive Extensions

以前、「C# LINQのクエリ式」./20130503247/ で少し触れたReactiveExtensionsについて、かなりたちましたがここでテストしてみたいと思います。

ReactiveExtensionsについて、多くの記事がある以下のサイトを参考にしました。

http://blog.okazuki.jp/entry/20120219/1329663635

特にここにある合成について興味があり、3つの値を監視して合成してみました。

環境 : Mono 4.2.0 / Mac OSX 10.10.5

https://www.nuget.org/でダウンロードしたnuget.exeで

mono nuget.exe install Rx-Main

を実行。インストールされる.dllファイルをプログラムファイルと同じパスにコピーして使用しました。

combine.cs

using System;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Reactive.Concurrency;

class Program {
    static void Main(string[] args) {

        var source1 = new Subject<string>();
        var source2 = new Subject<int>();
        var source3 = new Subject<int>();

        source1.CombineLatest(
            source2.Where(n => n % 2 == 0).Select(i => i * 10),
            (l, r) => string.Format("{0} | {1}", l, r))
        .CombineLatest(
            source3.Take(2),
            (l, r) => string.Format("{0} || {1}", l, r))
        .Subscribe(
            s => Console.WriteLine("* OnNext: {0}", s),
            () => Console.WriteLine("* OnCompleted"));

        Console.WriteLine("source1:'foo1'");
        source1.OnNext("foo1");
        Console.WriteLine("source1:'foo2'");
        source1.OnNext("foo2");

        Console.WriteLine("source2:22");
        source2.OnNext(22);

        Console.WriteLine("source3:311");
        source3.OnNext(311);
        Console.WriteLine("source3:312");
        source3.OnNext(312);
        Console.WriteLine("source3:313");
        source3.OnNext(313);

        Console.WriteLine("source1:'bar1'");
        source1.OnNext("bar1");
        Console.WriteLine("source2:23");
        source2.OnNext(23);
        Console.WriteLine("source2:24");
        source2.OnNext(24);

        Console.WriteLine("source1:Completed!");
        source1.OnCompleted();
        Console.WriteLine("source2:99");
        source2.OnNext(99);
        Console.WriteLine("source2: Completed!");
        source2.OnCompleted();

        Console.ReadLine();
    }
}

ビルドと実行

mcs combine.cs -r:System.Reactive.Core.dll,System.Reactive.Linq.dll,System.Reactive.Interfaces.dll
mono ./combine.exe

実行結果

source1:’foo1′
source1:’foo2′
source2:22
source3:311
* OnNext: foo2 | 220 || 311
source3:312
* OnNext: foo2 | 220 || 312
source3:313
source1:’bar1′
* OnNext: bar1 | 220 || 312
source2:23
source2:24
* OnNext: bar1 | 240 || 312
source1:Completed!
source2:99
source2: Completed!
* OnCompleted

リアクティブプログラムなのに、オブザーバという言葉がでてきませんが、SubjectクラスにはIObservableとIObserverの両方のインターフェースを実装されているようです。
監視対象の値が3つとも用意されたタイミングで、表示しています。最近のプログラムは非同期処理、関数型言語の文法の普及等により、プログラムの読み方が昔のように上から下に処理が流れていくような作りから、かなり変わってきたということをしみじみと感じます。

SQLite for Excel

一つのファイルでデータベースを扱える手軽さから、さまざまなプラットホームで使われているSQLite。Excelから直接扱えることを知り、テストしてみました。

http://sqliteforexcel.codeplex.com/

このサイトからダウンロードしたファイルだけで、特に何かインストールすることなくDBファイルに読み書きできました。
Distributionフォルダにある、SQLiteForExcel_64.xlsmを使用。
sqlite3.dllはx64フォルダのものに変更します。

環境 : Excel 2013 / Windows 10
このファイルには、SQlite3とSQlite3DemoというVBAモジュールがすでに組み込まれており、SQlite3Demoを参考に以下のプログラムを作成しました。
ボタン1でDBの作成、データ書き込み、ボタン2でDB読み込みセルに表示をしています。

Sub ボタン1_Click()
    Dim InitReturn As Long
    Dim testFile As String
    Dim RetVal As Long
    Dim myDbHandle As LongPtr
    Dim myStmtHandle As LongPtr
    
    InitReturn = SQLite3Initialize
    If InitReturn <> SQLITE_INIT_OK Then
        Debug.Print "Error Initializing SQLite. Error: " & Err.LastDllError
        Exit Sub
    End If
    
    testFile = "C:\temp\Test01.db3"
    RetVal = SQLite3Open(testFile, myDbHandle)
    Debug.Print "SQLite3Open returned " & RetVal

    RetVal = SQLite3PrepareV2(myDbHandle, "CREATE TABLE MySecondTable (TheId INTEGER, TheText TEXT, TheValue REAL)", myStmtHandle)
    Debug.Print "SQLite3PrepareV2 returned " & RetVal
    
    RetVal = SQLite3Step(myStmtHandle)
    Debug.Print "SQLite3Step returned " & RetVal

    RetVal = SQLite3Finalize(myStmtHandle)
    Debug.Print "SQLite3Finalize returned " & RetVal
    
    RetVal = SQLite3PrepareV2(myDbHandle, "INSERT INTO MySecondTable Values (123, 'ABC', 42.1)", myStmtHandle)
    Debug.Print "SQLite3PrepareV2 returned " & RetVal
    RetVal = SQLite3Step(myStmtHandle)
    Debug.Print "SQLite3Step returned " & RetVal

    RetVal = SQLite3PrepareV2(myDbHandle, "INSERT INTO MySecondTable Values (456, 'DEF', 12.3)", myStmtHandle)
    Debug.Print "SQLite3PrepareV2 returned " & RetVal
    RetVal = SQLite3Step(myStmtHandle)
    Debug.Print "SQLite3Step returned " & RetVal
    
    RetVal = SQLite3PrepareV2(myDbHandle, "INSERT INTO MySecondTable Values (789, 'GHI', 45.6)", myStmtHandle)
    Debug.Print "SQLite3PrepareV2 returned " & RetVal
    RetVal = SQLite3Step(myStmtHandle)
    Debug.Print "SQLite3Step returned " & RetVal
    
    RetVal = SQLite3Finalize(myStmtHandle)
    Debug.Print "SQLite3Finalize returned " & RetVal

    RetVal = SQLite3Close(myDbHandle)


End Sub

Sub ボタン2_Click()
    Dim testFile As String
    Dim RetVal As Long
    Dim myDbHandle As LongPtr
    Dim myStmtHandle As LongPtr
    
    testFile = "C:\temp\Test01.db3"
    
    RetVal = SQLite3Open(testFile, myDbHandle)
    Debug.Print "SQLite3Open returned " & RetVal
    
    RetVal = SQLite3PrepareV2(myDbHandle, "SELECT * FROM MySecondTable", myStmtHandle)
    Debug.Print "SQLite3PrepareV2 returned " & RetVal
    
    RetVal = SQLite3Step(myStmtHandle)
    Debug.Print "SQLite3Step returned " & RetVal

    r = 1
    Do While RetVal <> SQLITE_DONE
        Cells(r, 1).Value = SQLite3ColumnText(myStmtHandle, 0)
        Cells(r, 2).Value = SQLite3ColumnText(myStmtHandle, 1)
        Cells(r, 3).Value = SQLite3ColumnText(myStmtHandle, 2)
        RetVal = SQLite3Step(myStmtHandle)
        r = r + 1
    Loop
    
    RetVal = SQLite3Finalize(myStmtHandle)
    Debug.Print "SQLite3Finalize returned " & RetVal
    
    RetVal = SQLite3Close(myDbHandle)

End Sub

実行結果。
sqliteExcel

DB Browser for SQLiteでDBファイルの内容を確認。
sqliteExcel02

データベースのデフォルトデータを作成する用途に便利だと思いました。

Data Interpolation / Excel

既知のデータ列に対して、その区間を補間してデータをなめらかにすることをExcelで実現しているとてもいい例を見つけましたので、試してみました。

参考: http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q1091176980

data

上下の散布図は、AB列、DE列に対応しています。データ補間がされているのがよくわかります。
三つの関数を組み合わせて実現されています。

Match関数
MATCH(D1,A:A,1)
A列全体からD1の値以下で最大値を検索してその場所がA列の何行目か取得

Offset関数
OFFSET($A$1,MATCH(D1,A:A,1)-1,1,2,1)
OFFSET($A$1,MATCH(D1,A:A,1)-1,0,2,1)
Match関数で取得したセルの位置から演算対象範囲を取得(A1を基準に何番目か)
A列の2行、B列の2行を取得

Trend関数
=TREND(OFFSET($A$1,MATCH(D1,A:A,1)-1,1,2,1),OFFSET($A$1,MATCH(D1,A:A,1)-1,0,2,1),D1)
既知のB列とA列の値からD1に対する新しい値E1を演算
B列の2値の関係:A列の2値の関係 = D1 : E1

よく考えられていて、すばらしいと思いました。

FCell / Excel

.Net in Excel

http://fcell.io/

ExcelでC#やF#を使うとき、このブログでも紹介したことがありますが、VSTOなどの技術を使います。これにはVisual Studioが必要となりますが、このツールはExelだけで、プログラミングができます。まさにこんなプロダクトが欲しかった、と思っていたものです。

環境: Excel 2016 / Windows 10
インストールは、サイトよりダウンロードした、インストーラ
FCell31_32bit.msi
FCell31_64bit.msi
のどちらかを実行するだけです。

fcell01
(起動時読み込まれているところ・・)

上記サイトにとてもわかりやすいデモムービがあります。これをそのまま実行してみました。
fcell02
ユーザ定義関数を実行しているところですが、プログラムを変更すると(Buildボタン押下)セルに結果が反映されます。(リアクティブになっていること確認)
scaleArr関数は、配列数式になっているので、範囲指定した後CTRL+SHIFT+ENTERで決定する。
fcell03

とても素晴らしいです。
ライセンスが、Enterprise Licenceと、Site Licenceというものがありますが、Enterpriseは$1000とちょっと高めなのが残念です。

マイクロソフトのプロダクトで、Excel, PowerShell, F#が好きな私としては、このあたりもっと意欲的なものが出てきてほしいと思っています。こういったツールが純正品ででてくれるとうれしいのですが・・

Auto Generated Example-Driven Parsing

こんなことができるコマンドがPowerShellにあるとは知りませんでした。
任意のテキストをある規則性に基づいて自動的に整形してくれるものです。
規則については元のテキストの一部を利用してテンプレートをつくるだけです。

decodeブログ(http://decode.red/blog)のフィードを使ってテストをしてみました。

環境: PowerShell 5.0 / Windows 10
feed.txt

Geohash
2015年12月4日 23:51
ジオコード(地理座標)の一つで、緯度と経…
Entropy
2015年11月2日 23:04
エントロピーという熱力学で使われる概念は…
Haskell for Mac
2015年10月17日 16:08
関数型言語Haskellに、Xcodeの…
FPGA & GPU/OpenCL
2015年9月13日 13:22
インテルによるアルテラ買収のニュースは、…
Word Cloud / D3.js
2015年8月30日 19:36
前回のword2vecで利用したテキスト…
Word To Vector
2015年8月23日 18:05
以前から気になっていたword2vecを…
Signal Processing Toolkit
2015年7月8日 23:16
音声データをコマンドツールだけで処理でき…
Mathematica / Raspberry Pi 2
2015年6月27日 22:13
あのRaspberry Pi 2をようや…
Multi Layer Perceptron
2015年5月17日 22:13
ニューラルネットワークが簡単に実装できる…
Evaluate Code
2015年5月2日 13:24
コードを文字列データとして与え、プログラ…

これの一部を使って作ったのが下のテンプレートで、以下コマンドを実行します。

$templ=@’
{title*:Geohash}
{date:2015年12月4日} {time:23:51}
{description:ジオコード(地理座標)の一つで、緯度と経…}
{title*:Signal Processing Toolkit}
{date:2015年7月8日} {time:23:16}
{description:音声データをコマンドツールだけで処理でき…}
‘@

Get-Content .\feed.txt | ConvertFrom-String -TemplateContent $templ | Format-Table -AutoSize title, date, time, description

テンプレートの選び方によって結果も違ってくるので、いろいろと試す必要はあります。
実行結果
powershell01

なかなか面白いです。
ひさびさのPowerShellでした。やはりPowerShellいいですね。

参考:

http://www.powershellmagazine.com/2014/09/09/using-the-convertfrom-string-cmdlet-to-parse-structured-text/

Add-in / Office 2016

以前、以下の記事でJavaScriptによるExcelのデータ読み書きのテストをしましたが、VisualStudioを使ったものでした。

「Apps for Office」./20131104603/

今回は、共有フォルダからアドインを読み込む方法でテストをしてみました。環境について下記を参照しました。

参考) 「Office 2016で進化したOffice アドイン」http://www.ka-net.org/blog/?p=6213

XMLファイル、JavaScriptプログラムは下記を参考にしました。

参考) https://github.com/OfficeDev/office-js-snippet-explorer

https://github.com/OfficeDev/office-js-snippet-explorer/tree/master/excel-snippets/setValueInRange.js

プグラムは、ボタンを押すとExcelのシートに値を書き込むシンプルなものです。
Office2016_01

sample.xml

<?xml version="1.0" encoding="utf-8"?>
<OfficeApp xmlns="http://schemas.microsoft.com/office/appforoffice/1.1" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:type="TaskPaneApp">
  <Id>6492a0e5-b158-47da-9145-6804c67ed8d9</Id>
  <Version>1.0</Version>
  <ProviderName>Microsoft</ProviderName>
  <DefaultLocale>EN-US</DefaultLocale>
  <DisplayName DefaultValue="excel-js-snippet-explorer"/>
  <Description DefaultValue="Contains snippets for ExcelJS."/>
  <Capabilities>
    <Capability Name="Workbook"/>
  </Capabilities>

  <DefaultSettings>
    <SourceLocation DefaultValue="http://192.168.11.111/sample.html"/>

  </DefaultSettings>
  <Permissions>ReadWriteDocument</Permissions>
</OfficeApp>

Idは、

Wscript.Echo LCase(Mid(CreateObject(“Scriptlet.TypeLib”).GUID, 2, 36))

で生成できます。
このファイルを共有フォルダに置きExcelから選択します。
共有フォルダは、Excelを使用するWindowsに、C:\Shareのように作成して、共有設定します。
ここをExcelオプション->セキュリティセンタ->信頼できるアドインカタログのアドレスに追加します。(「メニューに表示する」をチェック)
Excelを起動して、挿入->マイアドイン->共有フォルダで、アドインが現れクリックします。
すると上の画面が表示されます。シート右側に表示されたWeb画面のボタンを押すと、数値が表示されます。
画面ファイルは、xmlファイルに書かれたアクセス先であるWebサーバをどこかに立て、そこに下記ファイルを置きます。

sample.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<script src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-2.1.4.min.js"></script>
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
<script>
Office.initialize = function(reason){}
$(function(){
  $("#btn").click(function(){
    Excel.run(function (ctx) {
      ctx.workbook.worksheets.getItem("Sheet1").getRange("A1:C3").values = 7;
      return ctx.sync();
    }).catch(function (error) {
      console.log(error);
    });
  });
});
</script>
</head>
<body>
<h3>Excel Add-in Test</h3>
<input id="btn" type="button" value="OK">
</bo
</html>

以前もこの件の記事を書いたときに思いましたが、JavaScriptとExcelという組み合わせは、とても可能性を秘めていると感じます。しかしまだ使いにくいと思います。もっと簡単に連携できるしくみが欲しいところです。シート上にWebViewが表示できればベストですが・・

Microsoft Edge

Windows10 で登場した新しいWebブラウザ、Edge。Windows95以来、約20年使われ続けた歴史あるブラウザInternet Explorerがとうとう交代することになりました。IEに関しては、いろんなケースで長年付き合ってきたので、感慨深いものがあります。当時インターネットの対応に出遅れたMicrosoftが、先行するNetscapeをつぶすため、無料でIEを配布したときは、とても話題になりました。それ以来、その独自路線にいろんな批判を浴びながらも、バージョンアップを重ねてきました。互換性を保ったバージョンアップが限界となり、ついに新しいブラウザの登場となったわけです。新しいブラウザEdgeは、独自仕様を排除し、Web標準を意識しています。
EdgeとIEの比較をテストサイトを使って、見てみました。

Edge
win_ed_html5

win_ed_octane

IE11 / Windows 10
win_ie11_html5

win_ie11_octane

当然のことながら、Edgeの方が数値的には勝っています。
Google Chrome ver45が、html5 526, Octane 15891でさらに上のスコアですが、IEに比べてかなりChromeに近づいてきました。asm.jsはEdgeの方が優れているという話もありましたが、この数値では、Chromeよりわずかに劣っているようです。(Chromeは31149) (asm.jsの性能に興味があったので、プログラムを作って比較したのですが、思った値にならなかったので、このOctaneを使うことにしました。)
数値がすべてではありませんが、差異を見る上では参考になります。
また、ユーザエージェントも調べてみました。

IE11

Mozilla/5.0 (Windows NT 10.0; Win64; x64; Trident/7.0; Touch; rv:11.0) like Gecko

Edge

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10240

かなり長くなっています。これを見ると、IEを完全に捨てていることがわかります。Webサーバには、ChromeまたはSafariとして認識してほしい、ということですね。
IE標準で作られた業務用Webアプリケーションなどは多数あるので、それらのためにIEを残しているというのは賢明だと思います。
互換性という過去しがらみから解き放たれ、リスタートした新しいブラウザに、今後期待したいと思います。

F# WPF Application

F#のみで、WPFアプリケーションが開発できるということを知り、久しぶりにF#を使ってみました。

参考 : Pure F# WPF GUIアプリ開発に向けて

http://qiita.com/nida_001/items/6ea321aff7f664a0e7f3

環境 : VisualStudio 2013 / Windows 10

オンラインで検索して、F# Empty Windows App (WPF)を選択します。

F#wpf_01

ツールボックスから部品を選択します。
F#wpf_02

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ViewModels;assembly=FsEmptyWindowsApp1"
    xmlns:fsxaml="http://github.com/fsprojects/FsXaml"
    Title="MVVM and XAML Type provider" Height="264.706" Width="472.059">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid Margin="0,0,2,16">
        <Button Content="Button"  Command="{Binding Path=ButtonPress}" HorizontalAlignment="Left" Margin="164,132,0,0" VerticalAlignment="Top" Width="75"/>
        <TextBox Text="{Binding Text01}" HorizontalAlignment="Left" Height="23" Margin="69,60,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
        <TextBox Text="{Binding Text02}" HorizontalAlignment="Left" Height="23" Margin="262,60,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120"/>
    </Grid>
</Window>

テキストボックスとボタンを関連づけます。

namespace ViewModels

open System
open System.Windows
open FSharp.ViewModule
open FSharp.ViewModule.Validation
open FsXaml

type MainView = XAML<"MainWindow.xaml", true>

type MainViewModel() as self = 
    inherit ViewModelBase() 
 
    let text01 = self.Factory.Backing(<@ self.Text01 @>, "")
    let text02 = self.Factory.Backing(<@ self.Text02 @>, "")
    member this.Text01 with get() = text01.Value and set(value) = text01.Value <- value
    member this.Text02 with get() = text02.Value and set(value) = text02.Value <- value
    member this.ButtonPress = self.Factory.CommandSync(fun () ->
        let str = text01.Value
        let len = String.length(str)
        if len = 0 then
            MessageBox.Show("Empty Value") |> ignore
        else if String.forall Char.IsDigit str then
            let x = str |> Double.Parse
            text02.Value <- (sqrt x) |> string
        else
            MessageBox.Show("Invalid Value") |> ignore
    )

関連づける部分が、馴染みがない方法なので、参考サイトがないとできませんでした。(ありがとうございます)

実行結果です。平方根を計算します。

F#wpf_03

簡単な入力チェックもしました。
F#wpf_04

なかなか使う機会がない言語は、とりかかりに時間がかかったりします。簡単な入力、出力を抑えておけば、次に必要になったとき、続きから作りやすくなるので、メモしておきたいと思います。


#
F#
Tags:

iOS, Android / VisualStudio 2015

前回に引き続き、iOS, Androidアプリのビルドを試してみました。
プロジェクトを作ろうとすると、Xamarinのインストールを要求されます。

vs2015_06

iOSのプロジェクトを選択します。
vs2015_ios01

おなじみのViewControllerのソースがC#で生成されました。
vs2015_ios02

実行しようとすると、Macが必要になるようです。
vs2015_ios03

iOSはここまでにして、次はAndroid。ユーザ登録をしておく必要があります。

Androidプロジェクトを選択します。
vs2015_and01

ソースが生成されました。
vs2015_and02

ビルドするとエミュレータが起動しました。

vs2015_and03

C#ですべて開発できる点は面白そうです。
しかし、iOSはやはりMacでしょうね。

VisualStudio 2015 / Windows 10

vs2015_01
新しいWindowsと開発環境が先月末リリースされました。
Windows 8 の迷走を収束させ、新しい方向性をうちだしているように見えます。
これまでWindowsストアアプリを開発していて感じたのは、タブレットという新しいデバイスを意識して、かなり大がかりな方向性の変化があったので、これまでのデスクトップアプリはなくなってしまうのではないか、と思うくらいでした。
今回、Windowsストアアプリ(もうこのようには呼ばないらしい..単にアプリ:ネーミングには毎回混乱させられます)はそのままに大きく振れた振り子を逆にもどすような動きをしているように見えます。

とりあえず気になるものから、試していきたいと思います。

環境 : Visual Studio Enterprise 2015 / Windows 10 Enterprise / Virtualbox 5.0.1
今回は、ユニバーサルアプリケーション UAP(Universal Applicatioon Platform)を試してみます。 
これは、一つのプログラムでWindowsを実装するあらゆるデバイスで動作させるアプリケーションのようです。
vs2015_02
自動で生成されるコードです。
vs2015_03
実行画面です。
vs2015_04
空白のアプリなので何も表示されてませんが、デバッグモードなのでフレームレートが表示されています。
シミュレータ実行すると以下のようになります。
vs2015_05
画面はWindowsデスクトップですが、これが各種Windowsデバイスに相当するのでしょう。

AndroidやiOSについても今後テストする予定です。

Windows 10 IoT

Raspberry Pi2でWindows IoT Coreを実行してみました。
開発するのに、Windows 10 Insider Preview も必要ということなので、インストールしようと思いましたが、私の環境ではできませんでした。
GPTディスクでないとインストールできないということですが、最近購入したPCでGPTなのにできませんでした。
しかしRaspberry Pi2で起動させるまでは、Windows 8.1でもできるようです。

環境: Windows 8.1

1) SDカードイメージとライティングツールの確認
IOT Core RPi.ISO (532,776,960 バイト)
をマウントすると、インストーラ(.msi)が入っているので、これを実行します。

インストールディレクトリ Program Files\Microsoft IoT

2) ディスク番号の確認
diskpart コマンド実行
>list disk

PhysicalDrive*
(* にドライブ番号)

Pi_dism

flash.ffuが書かれたSDカードをRaspberry Pi2に挿入して、起動。

Pi_tut01

チュートリアルを実行してみました。
Raspberry Pi2本体のグリーンLEDが点滅します。

この続きは、Windows 10 が動く環境ができてからにしたいと思います。

C++ Standard Template Library

最近は、すっかり使わなくなってしまいましたが、C++をちょっと見直す機会があり、再学習とこれから使うためのリファレンスの意味で、興味がある機能を並べてました。

環境 : VisualStudio 2010 / Windows 7

#include "stdafx.h"
#include <iostream>
#include <deque>
#include <algorithm>

using namespace std;
typedef deque<int> INTDEQUE;

void p(int n)
{
	cout << n << " ";
}
int main(array<System::String ^> ^args)
{
	INTDEQUE  dq;

	dq.push_front(3);
	dq.push_front(2);
	dq.push_front(1);
	dq.insert(dq.begin(), 0);
	dq.push_back(9);

	cout << "start : ";
	for_each(dq.begin(), dq.end(), p);
	cout << endl;

	INTDEQUE::reference reff = dq.front();
	INTDEQUE::reference ref2 = dq[2];
	INTDEQUE::reference refe = dq.back();

	reff = 10;
	ref2 = 12;
	refe = 19;

	cout << "refer : ";
	for_each(dq.begin(), dq.end(), p);
	cout << endl;

	dq.pop_front();
	dq.pop_front();

	cout << "pop   : ";
	for_each(dq.begin(), dq.end(), p);
	cout << endl;

	dq.push_back(21);
	dq.push_back(22);

	cout << "push  : ";
	for_each(dq.begin(), dq.end(), p);
	cout << endl;

	random_shuffle(dq.begin(), dq.end());

	cout << "shuff : ";
	for_each(dq.begin(), dq.end(), p);
	cout << endl;

	rotate(dq.begin(), dq.begin() + 1, dq.end());
    
	cout << "rotat : ";
	for_each(dq.begin(), dq.end(), p);
	cout << endl;

	dq.erase(dq.end()-2,dq.end());
	
	cout << "erase : ";
	for_each(dq.begin(), dq.end(), p);
	cout << endl;

	getchar();

    return 0;
}

実行結果
cppstl01
プロジェクトは「Visual C++ CLRコンソールアプリケーション」です。
実行結果に、コメントとその結果があるので、説明は省きます。

参考 : https://msdn.microsoft.com/ja-jp/library/f1dtts6s%28v=vs.90%29.aspx

Swift / Visual Studio 2013

最近一番注目している言語Swift。今のところMacでしか動作しませんが、他のプラットホームでも動作することが期待されます。そこでいろいろと調べてみたところ、Windowsで動作するものがありました。

Silver

http://elementscompiler.com/elements/silver/

上記サイトから評価版がダウンロードできたので、試してみました。
OxgeneというPascal言語を開発している会社のプロジェクトのようです。

以下Wikipediaより

http://en.wikipedia.org/wiki/Oxygene_%28programming_language%29

Oxygene (formerly known as Chrome) is a programming language developed by RemObjects Software for Microsoft’s Common Language Infrastructure and the Java Platform. Oxygene is Object Pascal-based, but also has influences from C#, Eiffel, Java, F# and other languages.

環境: Windows 2013 / Windows 8.1
silver1

起動すると上のような画面がでます。Swift以外の言語も選択できます。
.NETコンソールアプリケーションを実行する予定でしたが、ランタイムエラーが出たので、Javaのコンソールアプリを選びました。

silver_java

import java.util

let names = ["Swift", "CSharp", "Java"]
for name in names {
    println("Hello, \(name)!")
}

func nilcheck(n:Int?)->(){
    if let nn = n{
        println(n)
    }
    else{
        println("This value is nil.")
    }
}

var n1:Int? = 12345
nilcheck(n1)

n1 = nil
nilcheck(n1)

for i in 1...100 {
    print("*")
}

もっとSwiftらしいプログラムにしたかったのですが、mapとかコンパイルエラーとなってしまいます。特徴的なOptionalは動作したので、これのみにしました。

実行結果
silver2

参考までに、Cocoa, .NETのプロジェクトは以下のようになります。
Cocoaは
silver_cocoa

silver_dnet

Cocoaは、CrossBoxというサーバに登録しないいけないようです。

silver_CrossBox

あまり時間をかけてテストしていませんが、VisualStudioでSwiftが走っている様子は、期待感を持たせてくれます。

Scheme Shell / Cygwin

CygwinというWindows上でLinuxコマンドを実行できるとても便利なツールとして、これまでいろんなケースで使ってきました。
最近のマイブームによりSCSHというSchemeによるシェルを実行する環境を探していたとき、Ubuntuとかでチャレンジしたのですが、インストールがうまくいかず、結局このCygwinにいきつきました。さすがです!
SCSHは、一見Gaucheとも似ているように見えるのですが、Shellですので、実行コマンドを式に組み込めるところが面白いと思いました。
環境 : Windows 8.1
scsh03
Cygwinは32bit版である必要があります。

以下の例は、実行プログラムをシェルの中から呼んだみました。
スラッシュが式に使えるのが、ポイントだと思っています。
scsh01
scsh -c で式をパラメータに与えても実行できます。

また、PowerShellでも動きます。(コマンドレットは動作しません)
Cygwinのbinにパスを通しておく必要があります。
scsh02
(上記、(run (| (echo 123 + 456) (bc) (cat)) (> tempfile)) という、書き方も可です。)

http://scsh.net/

本家サイトを見ると、
The latest version of scsh is 0.6.7, released May 16, 2006:
ということで、ちょっと残念です。
この時点で動作させられるという記録を残しておく意味でも、とりあげてみました。
(こういうのBlogの役割かも)

参考サイト:
http://wiki.call-cc.org/eggref/4/scsh-process (以前取り上げたChickenSchemeのサイトにもあります。)

http://www.drdobbs.com/systems-administration-with-scsh/199101322

すばらしいです。

Azure Machine Learning

Microsoft Azureで今ホットな機会学習ができるということで、試してみました。
「Hadoop : HDInsight」以来久しぶりのAzureになりますが、名前もWindows Azureから変わったのですね。(URLはそのまま)

Azure管理メニューに追加されたMachine Learningから、簡単に準備ができました。
「ML Studioにサインイン」をクリックすると、manage.windowsazure.comからstudio.azureml.netに移動します。
azml01

experimentsのSAMPLESから最初のSample1を編集して使ってみました。
サンプル自体は、編集できないので、Save Asでコピーします。
azml02
azml03
Sample1は、インターネット上のCSVファイルにRのプログラムでヘッダを追加し、平均等の要約しています。(Descriptive Statistics)
私の方でさわったのは、Elementary Statisticsを追加して、年齢の最大値を取得するようにしたところと、元データが3万件を超えて処理が重いため、100件まで削除して自サイトからダウンロードできるようにしました。
azml04a

Launch Column Selectorをクリックします。
azml04b

実行(RUNクリック)後、Elementary Statisticsのアウトプットを右クリックしてVisualizeします。
azml04c

Descriptive StatisticsをVisualizeしたのが以下です。
azml05
100件になっています。

azml06a

機械学習まではまだまだですが、ひとまずデータの流れだけを練習してみました。

WCF Service Application

ASP.NETでOData、データソースにAccessファイルとか、いろいろとやりたいことがあるのですが、環境がすぐに用意できなかったり、うまくいかなかったりしたため、とりあえず基本となるWCFの部分だけ、メモっておこうと思います。
といっても、デフォルトである程度動くと見込んだものの、ちょっと戸惑いました。

環境 : Visual Studio 2013 / Windows 8.1

wcf06
WCFサービスアプリケーションで新規プロジェクトを作り、何も変更せずに実行しました。
WCFテストクライアントが立ち上がり、リクエスト、レスポンスのテストができます。
wcf01

ブラウザから、GETリクエストでレスポンスを得るために、以下のようにGetData2メソッドを追加しました。
(この追加をすると、上記のWCFテストクライアントでのテストはできなくなりました。自動でたちあがらくなり、コマンドwcftestclient.exe直接実行でもエラーがでます)

wcf07

Service1.csv.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService01
{
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }
        [WebGet(UriTemplate = "data/{value}")]
        public string GetData2(String value)
        {
            return string.Format("You entered: {0}", value);
        }
        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

IService1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace WcfService01
{
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);
        [OperationContract]
        string GetData2(String value);
        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
    }
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";
        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }
        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

まず以下のようにデフォルトの画面を確認して、
wcf05
パラメータを追加してみます。
wcf04
と表示するはずですが、以下のように設定を追加していないとBad Request となり白い画面になってしまいます。
Web.config

<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>

    <!--追加 -->
    <services>
      <service name="WcfService01.Service1">
        <endpoint address=""
                  behaviorConfiguration="restBehavior"
                  binding="webHttpBinding"
                  contract="WcfService01.IService1" />
      </service>
    </services>
    
    <behaviors>
      <!-- 追加 -->
      <endpointBehaviors>
        <behavior name="restBehavior">
          <webHttp helpEnabled="true"/>
        </behavior>
      </endpointBehaviors>
      
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

これにより、XML POSTリクエストも可能になります。
環境 : Cygwin / Windows 8.1
wcf08
最初、レスポンスが得られないとき、URLが違うのか、このやり方が違うのか迷いました。
結局、うまくいっているサンプルを探し、そのWeb.configファイルと比較したら、上のような違いをみつけました。
(Microsoftのプロダクトは、権限とか設定とかデフォルトで無効になっているものがよくあるように思います。
セキュリティを高めるためだとは思いますが、ちょっと動かしてみたいというときにできないと、次に進めなくてあきらめてしまいがちです。)
できたところまで、とりあえずメモでした。

IronScheme

今年最初の投稿は、新年早々IronSchemeです。(^^;

前回、Clojureをまわりを調べているときに、この存在を知り試してみようと思いました。
.NETフレームワークのライブラリが使用できるSchemeということですが、IronPython, IronRubyと同じように位置づけなのでしょう。

Lisp (+ List Processor))

http://decode.red/blog/20141201244/

ここで使用した順列のプログラムをIronSchemeで動かしてみました。

環境 : Windows 8.1

https://ironscheme.codeplex.com/

IronScheme-109887.zip

perm.ss

(import (srfi :1 lists))

(define (perm ls a)
    (if (null? ls)
        (display (reverse a))
        (for-each
            (lambda (n)
                (perm (remove (lambda (a) (equal? a n)) ls)(cons n a)))
            ls)))

(perm '(1 2 3) '())
(newline)

冒頭のimportの記述や、コマンド実行時ファイル指定の方法にちょっと迷いました。

hello.ss

(import (rnrs))

(display "Hello")
(newline)

上の二つのプログラムをそれぞれ以下のように実行しました。

IronScheme02

最初、srfiの指定方法がいけないのかどちらかわかりませんでしたが、リダイレクトの方法だとうまくいくので、とりあえずこのままにしました。

次に、下記サイトを参考に、VisualStduio 2013を使ってC#から呼び出してみました。

http://cryks.hateblo.jp/entry/20120417/1334660328

インストールは、NuGetを使いました。
IronScheme01

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using IronScheme;
using IronScheme.Runtime;

namespace csConsScheme01
{
    class Program
    {
        static void Main(string[] args)
        {
             Console.WriteLine("(+ 1 2 3)".Eval());
             Console.ReadKey();

             "(define (add x y)(+ x y))".Eval();
             var add = "add".Eval<Callable>();
             Console.WriteLine(add.Call(1, 2));
        }
    }
}

出力は、6と3です。
特定の処理だけ組み込み言語的に使う用途にいいかもしれません。

calling Clojure from C#

.NETフレームワークがオープンソースになるということですが、C#のプログラムがJavaのようにクロスプラットホームで使われるようになるかもしれません。
Javaの資産は膨大なものがありますので、これをC#から呼び出す方法を試してみようと今回思いました。以前、JNIを使ってC++/CLIからJava(./2013021475/)を呼び出すテストをしたことがありますが、これはちょっと面倒なので、もっと簡単な方法はないかと調べたら、いいのがありました。

http://jni4net.com/

bridge between Java and .NET (intraprocess, fast, object oriented, open-source)

Java と.NET相互に呼び出しが簡単にできそうです。今回は.NETからJava呼び出しのみテスト。
しかしあまりあっけなくできてしまったので、もう少し踏み込んで、Clojureの呼び出しをしてみました。
JavaからClojureの呼び出しは、こちら(http://bitlife.me/archives/297)でテストした、プログラムを使い、このJavaプログラム部分を変更して、C#から呼び出します。

環境 : jni4net 0.8.8, Java 1.8.0_25, Visual Studio 2013 Update3 / Windows 8.1
JavaMainCs.java

import clojuresub.core;

public class JavaMainCs{
	public static void sub(String str){
		core.sub(str);
	}
}

Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using net.sf.jni4net;

namespace CSharpMain
{
    class Program
    {
        static void Main(string[] args)
        {
            var bs = new BridgeSetup();

            bs.AddClassPath(@"C:\wk\", true);
            bs.AddAllJarsClassPath(@"C:\wk\");

            Bridge.CreateJVM(bs);

            java.lang.Class jclass = 
                java.lang.ClassLoader.getSystemClassLoader().loadClass("JavaMainCs");

            java.lang.Class[] cls = { java.lang.String._class };
            java.lang.Object[] obj = { new java.lang.String("C# String") };

            java.lang.reflect.Method method = jclass.getMethod("sub", cls);
            method.invoke(null, obj);

            Console.ReadKey();
        }
    }
}

C#のコードの中にJavaが書けてしまい、ちょっと不思議な感覚になります。

VisualStudioでは参照追加とビルド設定をします。
clojure_cs01

以下のようにファイルを配置して実行しました。(JavaMain.classは前のテストのものなので不要)
clojure_cs02

最近、Lispを再勉強中ということもあって、Java環境ではClojureを使っていましたが、この記事を書きながらいろいろと調べていたら、WindowsにはIronSchemeというものがあることを知りました。次回、これをとりあげてみたいと思います。

Access .mdb / PowerShell

AccessのmdbファイルをPowerShellで読み込むテストをしてみました。
ファイルベースのDBで簡単にデータをプログラムで活用するために、とても便利です。

環境 : Access 2013, PowerShell 4.0 / Windows 8.1 64bit
まずからの空のmdbファイルをせっかくなので、PowerShellでつくりました。
ここで注意することは、32bit版のPowerShellを使う必要があることです。

$para = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source='C:\work\sample01.mdb'"
$obj = New-Object -ComObject "ADOX.Catalog"
$mdb = $obj.Create($para)
$mdb.Close()

これをAccessで開き、適当なテーブルを作成します。
access01

Accessは開いたまま下記コマンドを実行できます。
select01.ps1

$conn = New-Object -comobject ADODB.Connection  
$rset = New-Object -comobject ADODB.Recordset  
  
$conn.Open("Provider = Microsoft.Jet.OLEDB.4.0; Data Source = C:\work\sample01.mdb")  
$rset.Open("Select * from table1", $conn)
$rset.MoveFirst()  
do {
	$rset.Fields.Item("item1").Value;
	$rset.MoveNext()
} until ($rset.EOF -eq $True)  
  
$rset.Close()  
$conn.Close() 

access02

32bit版のPowerShellをショートカットにして、起動したところです。

参考:

http://hidori.jp/blog/2013/04/03/610

https://gallery.technet.microsoft.com/office/a4a0ade2-e856-48ff-9e91-31b4b6356382

Excel Services REST API / SharePoint

SharePointには以前から興味を持っていましたが、最近Excelの機能で使いたいことがあり、それに関連してREST APIのテストしてみました。

環境 : Excel 2010 / Windows 7, SharePoint 2013 / Windows 2012R2
sp01
まず上のようなB,C列のデータをグラフ表示する簡単なシートを作りました。(グラフの名前をGraph1とします)
A1の初期値を変えると、B,C列のデータも変化します。
これを普通にファイルを保存すると同じように、サーバに保存します。
普通に、といったのは、ファイル名のところに、下のURLを記入するからです。

http://[ShaerPointサーバ名]/sites/cata01/docApp/Book2.xlsx

何か違和感がありますが、これで認証ポップアップがでてきて、サーバに保存します。
URLはSharePointサーバであらかじめ設定したドキュメントを置く場所をさします。

sp02
SharePointのドキュメントリストをみると、保存されているのがわかります。
そして、これをブラウザ上で表示してみます。
sp03

次に、REST APIを使って、データを変更して、グラフを変えてみます。

http://[ShaerPointサーバ名]/sites/cata01/_vti_bin/ExcelRest.aspx/docApp/Book2.xlsx/model/Charts(‘Graph1′)?Ranges(‘A1′)=0.05

sp04

http://[ShaerPointサーバ名]/sites/cata01/_vti_bin/ExcelRest.aspx/docApp/Book2.xlsx/model/Charts(‘Graph1′)?Ranges(‘A1′)=0.8

sp05

URLでこのようにExcelシート内部のデータを操作できるのが、とても興味深いです。
Webということは、JavaScript連携も可能ということなので、またの機会にやってみたいと思います。

参考 : http://msdn.microsoft.com/ja-jp/library/ee556413.aspx

Background Inteligent Transfer Service

BITSというPowerShellのファイルの分割ダウンロードをやってみました。
本当に分割リクエストをしているのか、また途中でサスペンドして、レジュームで継続してダウンロードするか、をApacheを使って確認しました。

環境 : PowerShell 2.0 / Windows 7 (192.168.11.10), apache2 / Ubuntu 14.04 (192.168.11.14)
Webサーバの準備。

dd if=/dev/zero of=dummy.zip bs=1M count=200

ダミーファイルを/var/www/htmlに作成。

LogFormat “%h %l %u %t \”%r\” %>s %O \”%{Range}i\”" combined

レンジがわかるように/etc/apache2/apache2.confのLogFormatを変更。

tail -f /var/log/apache2/access.log

でログ確認。サスペンドは20秒ほど。(改行部分)

BTS02

転送が始まって、少ししたら、サスペンド、そしてレジューム。
サスペンドするために、非同期で実行。

BTS01

レンジが指定できないようなのが、ちょっと不便な気がします。自動的に調整しているみたい。
サスペンドして、Windows7を再起動後、レジュームしても途中からダウンロードしました。
巨大ファイルを何日かかけてダウンロードする用途があるときは、便利。

PowerShell DSC / Hyper-V

PowerShell 4.0の新しい機能である、Desired State Configurationを使ってみました。

参考:PowerShell DSCによるプッシュ型展開

http://www.atmarkit.co.jp/ait/articles/1407/24/news131.html

このDSCというのは、サーバの設定を自動的にするしくみで、リモートホストとPushおよびPull通信をします。

ここでは、Windows Server 2012R2のHyper-VにWindows 8.1を仮想化した環境で、2012R2から8.1へのPushをテストしました。
設定するものは、ファイルリソースを使って、メッセージを指定のフォルダに書き込み見ます。

8.1側は以下の設定を事前にします。

Enable-PSRemoting -Force
Set-Item wsman:\localhost\Client\TrustedHosts -Value * -Force
Set-ExecutionPolicy RemoteSigned

hello.ps1

Param([string]$msg)

Configuration DSCTest
{
    Node "192.168.11.11"
    {
        File dscFile
        {
            DestinationPath = "C:\work\hello.txt"
            Ensure = "Present"
            Type = "File"
            Contents = $msg
        }
    }
}
$outputPath = ".\DSCTest"
DSCTest -OutputPath $outputPath
Start-DscConfiguration -Path $outputPath -Wait -Verbose -Credential 192.168.11.11\user

結果
dsc01

冪等性から、何度設定しても同じ状態になる特徴がありますが(同じ状態だと何もしない)、
上のようにメッセージを引数で変えてやると、毎回設定にいくようです。

対象ノードは複数設定でき、いろいろと応用した使い方ができそうです。

PowerShellでLDAP

LDAPのデータ操作をPowerShellでやってみました。ActiveDirectoryでも同様にできると思いますが、汎用性と導入のしやすさを考えて、OpenLDAPを使いました。

環境 : PowerShell 2.0 / Windows 7 <-> OpenLDAP 2.4.31 / Ubuntu 14.04 LTS

OpenLDAPのインストールは以下のコマンドを実行しただけ。

apt-get install ldap-utils
apt-get install slapd

自動で起動し、使用可能となります。
認証は、cn=admin,dc=nodomain / password
ホスト名は設定していないので、nodomainのままですが、これで使えるようになるのはスゴイ!
テスト前に、データを適当に作成しておきます。(ldapmodifyでもいいですが、ApacheDirectoryStudioを使用)

まずデータの参照から。

$domain = "LDAP://192.168.11.11:389/dc=nodomain"
$auth = [System.DirectoryServices.AuthenticationTypes]::FastBind
$root = New-Object System.DirectoryServices.DirectoryEntry($domain,"cn=admin,dc=nodomain", "password", $auth)
$query = New-Object System.DirectoryServices.DirectorySearcher($root,"(objectclass=*)")
$entries = $query.FindAll()
$entries | %{$_.Properties}
$entries[5] | %{$_.Properties}
$entries[5] | %{$_.Properties["cn"]}
$entries[5] | %{$_.Properties}).PropertyNames

ldap01

更新対象のuser02のデータのみを確認してみます。
ldap02

次に、属性の追加・更新。

$query = New-Object System.DirectoryServices.DirectorySearcher($root,"(&(objectclass=*)(uid=user02))")
$entry = $query.FindOne().GetDirectoryEntry()
$entry.description.Value="Add Value by PS"
$entry.SetInfo()
$entry.givenname.Value="Edit Test"
$entry.SetInfo()

$query.FindOne() | %{$_.Properties}

ldap03

user02にデータが更新されていることが確認できます。

LDAPデータをPowerShellオブジェクトとして扱えるのは便利。

PowerShellでJSON

PowerShellには、PowerShellオブジェクトとJSONデータを相互に変換できる便利なコマンドレットがあります。

ConvertTo-Json
ConvertFrom-Json

今回のテストで使うJSONデータは、WebからPowerShellで取得します。
今日は台風ということもあって、天気情報を取得してみたいと思います。
情報元は、ライブドア天気情報の名古屋地区のものです。

環境: PowerShell ver3.0 / Windows 8

$wr = Invoke-WebRequest -uri http://weather.livedoor.com/forecast/webservice/json/v1?city=230010

($wr.Content | ConvertFrom-Json).description.text

wr01

wr02e

なかなか実用的なテストになりました。

Multithreading PowerShell

PowserShellを使ったマルチスレッドをテストしてみました。
1秒から10秒までスリープするスレッド10個を同時に走らせています。
AddScript, AddArgmentによるパラメータ渡し、結果取得をイメージするため、2乗する演算をいれています。(手抜き感・・)
ソースは下記サイトにあるものを簡略化しました。

環境 : PSVersion 2.0 / Windows 7


$threads = 10
 
$scriptBlock = {
   Param (
      [int]$num
   )
   Start-Sleep -Seconds $num
   $res = New-Object PSObject -Property @{num=$num;num2=$num*$num}
   Return $res
}
 
$runspacePool = [RunspaceFactory]::CreateRunspacePool(1, $threads)
$runspacePool.Open()
$jobs = @()

1..10 | % {
   $job = 1::Create().AddScript($scriptBlock).AddArgument($_)
   $job.runspacePool = $runspacePool
   
   $jobs += New-Object PSObject -Property @{
      num = $_
      pipe = $job
      result = $job.BeginInvoke()
   }
}
ForEach ($job in $jobs)
{   
     $job.pipe.EndInvoke($job.result)
}

multiPS
結果が1行/1秒ごとに表示されるので、同時に走っていることが確認できます。
$threads数を絞ると、表示終了までにさらに時間がかかることも確認できます。

参考サイト : http://thesurlyadmin.com/2013/02/11/multithreading-powershell-scripts/

C# Interactive / Mono

前回のF# Interactive / Monoの記事を書いたとき、C#では同様なことはできないと思いこんでいましたが、シェルスクリプトの形式で書けることがわかり、テストしてみました。

csi01

この二つ目まではC#でもできそうだとわかっていましたが、三つ目のような #!/usr/bin/csharpという書き方ができるとは知りませんでした。
(Perlなどと同様)

ということは、

#!/usr/bin/csharp

while(true){
	var str = Console.ReadLine();
	if(str == null){
		break;
	}
	Console.WriteLine("{0} : Length {1} ", str, str.Length);
}

ということができる(標準入力が受け取れる)ということで、以下が結果です。

csi02

LinuxだとShellが強力なので、このような書き方ができるということは、とてもありがたく思えます。


#
C#
Tags:

F# Interactive / Mono

これまで.NET環境はWindowsだけでしか使ったことがありませんでしたが、はじめてMono(Linuxの.NET環境)をUbuntu上でインストールしてみました。自宅の環境の都合で、F#をLinuxで使うと、いろいろと便利に思ったからです。

もともとLinux上でPowerShellが完全に動作してくれればそれでもよかったのですが、その実装のPash (http://pash.sourceforge.net/) がちょっと古めなので、追いかけるをやめて、F# Intaractive (fsharpi, fsi.exe)環境でやりたいことを実現することにしました。
ここでは、環境についてメモっておきたいと思います。
(PowerShellはオブジェクトのパイプライン処理、Linuxのシェルはテキストのパイプライン処理ですが、JSONファイルをオブジェクトと見立たててみると面白いかも・・ということで、FSharp.Dataを利用)

環境 : Ubuntu 14.04 LST(64bit) / VirtualBox 4.3.10 / Windows 7
[Mono,FSharpのインストール]

sudo apt-get update
sudo apt-get install mono-complete
sudo apt-get install fsharp

[FSharp.Dataのインストール]

https://github.com/fsharp/FSharp.Data

ここにあるソースでビルドを試みましたが、build.sh実行時に失敗。
fsharpi build.fsx のfsharpiを違うバージョンで試すとビルドを始めましたが、途中でエラー。
NuGetでインストールする方法に変更。

参考) http://monomvc.wordpress.com/2012/03/06/nuget-on-mono/

http://nuget.codeplex.com から NuGet.exeをダウンロード(なんと単一ファイル)
/optに配置して実行

mozroots –import –sync
mono NuGet.exe install FSharp.Data

以下サンプルプログラム

Ubuntu_fsx
参考)http://fsharp.github.io/FSharp.Data/library/JsonProvider.html

コンパイルなしに利用できます。このあたりダイナミック言語ライクに使えるところがいいです。
ちょっと処理速度は遅いですが。。


#
F#
Tags:

MSMQ / PowerShell

ErlangつながりでRabitMQに興味をもち、別件でテストしていたとき、MSMQというWindows標準のメッセージキューシステムがWindowsにあることを知りました。(順序が逆か?)
そこでいろいろと調べてテストをしましたが、自分の思う形で動かすのに少し手こずりました。

環境 : Windows 7 & Windows 8.1

・ドメインモードとワークグループモードがあり、ワークグループモードでは、プライベートキューのみ
・リモート接続ではプライベートキューへの送信がサポートされていない(?)

といったことから、2台のPCで通信したかったのですが結局Windows7ローカルのみでテストすることにしました。

サーバ設定
msmq_c

送信側
msmq_s

受信側
msmq_r

PowerShellで簡単に実装できるので、いろんなケースで活用できそうです。
MSMQにかぎらず、MessageQueueはいろいろとホットなので、もう少し掘り下げてみたいです。

PowerShell C# Cmdlet 2

前回コマンドレットからの出力をやりましたので、今回はコマンドレットへの入力もおさえておきたいと思います。

using System;
using System.Management.Automation;

namespace InputTest
{
    [Cmdlet(VerbsCommon.Get, "Para")]
    public class GetGreeting : Cmdlet
    {
        [Parameter(ValueFromPipelineByPropertyName = true)]
        public string BaseName { get; set; }

        [Parameter(ValueFromPipelineByPropertyName = true)]
        public string Extension { get; set; }

        protected override void ProcessRecord()
        {
            Console.WriteLine(BaseName + " : " + Extension);
        }
    }
}

前回と環境は同じで、同様に実行させます。
PowerShell02
lsはGet-ChildItemのエイリアスで、ディレクトリのファイルリストのオブジェクトを返します。
表示はされていませんが、オブジェクトに含まれています。
以下、念のため。
PowerShell03

PowerShell C# Cmdlet

ひさしぶりのPowerShellのネタです。
PowerShellを使っていて、ふとコマンドレットって、自分でどうやって作るの? と思い、作ってみました。
いきなりですがテスト結果です。
PowerShell01
このようにヘッダがあり、検索ができる形のオブジェクトを出力したかったのですが、調べてみるといろんなやり方がありそうです。結果、anonymous typeを使って実現する方法が簡単で自分の求めていた形になりました。

using System;
using System.Collections.Generic;
using System.Management.Automation;

namespace SumTest
{
    [Cmdlet(VerbsCommon.Get, "Sum")]
    public class Get_DemoNames: PSCmdlet
    {
        protected override void ProcessRecord()
        {
            List<object> list = new List<object>();

            int sum = 0;
            for(int i=10 ; i<16;i++){
                sum += i;
                var data = new {Sum = sum,  Num = "No" + i, Name = "Name" + i};

                list.Add(data);
            }

            this.WriteObject(list, true);
        }
    }
}

パッケージのインストールが必要です。

PM> Install-Package System.Management.Automation

環境 : VisualStudio 2010 / Windows 7

プロジェクトは、アプリケーションではなく、クラスライブラリのようです。

Haskell from C#

Haskell from Excel という過去の投稿で、C++からのHaskell呼び出しをやりましたが、C#から直接できることを以下のサイトで知り、テストしてみました。

Calling Haskell from C#

http://stackoverflow.com/questions/16615641/calling-haskell-from-c-sharp

このサイトでは、Monoで実行していますが、Windowsでテストしました。
また、Stringを戻り値とする関数が使いたかったので、これを追加しています。

環境: GHC ver 7.6.3, VisualStudio 2010 / Windows 7
Foo.hs

module Foo where

import Foreign.C.String
import Foreign.C.Types
import Data.List.Split

foo :: CString -> IO CInt
foo c_str = do
	str    <- peekCString c_str
	result <- hs_foo str 
	return $ fromIntegral result

hs_foo :: String -> IO Int
hs_foo str = do
	putStrLn str
	return (length str)

hstest :: CString -> IO CString
hstest c_str = do
	str <- peekCString c_str
	let s = concat $ fmap cadd $ chunksOf 1 str
	newCString s

cadd :: String -> String
cadd c = do
	c ++ " "

foreign export ccall foo :: CString -> IO CInt
foreign export ccall hstest :: CString -> IO CString

ghc -no-hs-main -shared -o Foo.so Foo.hs

hstestで、C文字列をHaskell文字列に変換し、文字列操作をして、またC文字列に戻しています。

次にC#側ですが、VisualStudioのC#コンソールアプリケーションプロジェクトで作成します。
Program.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace csConsoleHaskell01
{
	class Program
	{
		[DllImport("Foo.so", CallingConvention = CallingConvention.Cdecl)]
		private static extern void hs_init(IntPtr argc, IntPtr argv);

		[DllImport("Foo.so", CallingConvention = CallingConvention.Cdecl)]
		private static extern void hs_exit();

		[DllImport("Foo.so", CallingConvention = CallingConvention.Cdecl)]
		private static extern int foo(string str);

		[DllImport("Foo.so", CallingConvention = CallingConvention.Cdecl)]
		private static extern IntPtr hstest(string str);

		static void Main(string[] args)
		{
			hs_init(IntPtr.Zero, IntPtr.Zero);

			int result = foo("Hello!");
			Console.WriteLine("Length : {0}", result);

			IntPtr r = hstest("Hello_Haskell_String");
			string s = Marshal.PtrToStringAnsi(r);
			Console.WriteLine(s);

			hs_exit();
		}
	}
}

intを戻すときは、そのままでしたが、stringは上のようにポインタを取得してから変換する必要があるようです。(戻り値stringは不可)
Haskell Foo.soをcsConsoleHaskell01\bin\Debugディレクトリにおいて、csConsoleHaskell01.exeをコマンドプロンプトで実行します。

Hello!
Length : 6
H e l l o _ H a s k e l l _ S t r i n g

このように表示されます。
.NetとHaskellを結びつけるには、HaskellのFFI(ForeignFunctionInterface)を使ってC++/CLIとリンクして、さらに.Netマネージコードと連携しなくてはいけないと思っていましたが、このように簡単にできてしまうのですね。C#-Haskellができると、ここからいろいろと派生できそうです。

Erlang Riak & Excel

XLLoopというExcelのアドインとサーバの組み合わせで、Excelのユーザ定義関数からサーバロジックを呼び出せる面白いものをみつけたのでテストしてみました。

http://xlloop.sourceforge.net/

サーバには、なんと最近勉強をはじめたErlangがあったので、これを使ってみました。
Erlanの分散データベースRiakのデータをExcelに表示させます。
残念ながら、RiakクライアントがWindowsでうまく動いてくれなかったので、HTTPクライアントによる接続にしました。

環境 XLLoop ver 0.3.2, Excel 2010 / Windows 7

-module(server_example).
-export([start/0, stop/0, function/3]).
-behaviour(xlloop_server).
-define(PORT, 5454).

start() ->
	Pid = xlloop_server:start(?PORT, ?MODULE),
	io:format("server port : ~p~n", [?PORT]),
	register(server_example_pid, Pid),
	
stop() ->
	server_example_pid ! stop.

function(_Context, _Name, _Args) ->
	io:format("name : ~s~n", [_Name]),
	io:format("args : ~w~n", [_Args]),

	case _Name of
		"riak" -> 
			[H|T] = _Args,
			io:format("arg : ~s~n", [H]),
			Url = string:concat("http://192.168.11.11:8098/buckets/spam/keys/", H),
			{ok, {{V,200,R},Head,Body}} = httpc:request(Url),
			{str, Body};
		_ -> {str, "default"}
	end.

ソースはxlloop付属のものを参考にしました。
(io:formatはデバック用です。)

xlloop-0.3.2.iniにErlangサーバ用の設定を加えます。

[Erlang]
server=localhost:5454
function.name=ER

以下Erlangシェルで実行します。

inets:start().
c(server_example).
server_example:start().

xlloop-0.3.2.xllをExcelシートにドラッグ&ドロップします。

RiakはWindowsをサポートしていないので、Mac版を使いました。

http://basho.co.jp/riak/

環境 riak ver 1.4.7 / MacOSX 10.9
IPアドレス192.168.11.11

ulimit -n 4096
sudo ./riak start

Riakについは、SoftwareDesignPlus「データベースエンジニア養成読本」を参考にしました。

Excelからは、=ER(“riak”, “キー値”)で呼び出します。
raik

Erlangはちょっと文法的に好きになれない点がありますが、小さなプロセスを組み合わせてメッセージ通信で動かすしくみがとてもユニークで、いろいろとプログラムを作っているところです。たくさんの言語、環境がありますが、どれに絞るというより、それぞれが他に比べて得意とするところをうまく利用していきたいと思っています。
学習コストはかかりますが、モノの見方の多様性を養うことができるのでは、と思っています。

SPARQL in Excel

今年はじめての投稿になります。
このBlogは初めてちょうど、一年になります。自分の技術向上の目的もこめて最低でも月一回はそのとき興味のあるプログラムネタを投稿しようと決めていましたが、一年なんとかやりきることができました。また今年もがんばりたいと思います。

本年もよろしくお願いいたします。

昨年からOpenDataに興味を持ち、O’Reilly「セマンティックWebプログラミング」等の書籍を読んで部分的なテストはしていましたが、実際に動くものが手元に欲しくなったので、この本のサンプルを参考にSPARQLというクエリー言語を使って試してみました。
取得したデータをExcelに読み込みたかったので、以前の投稿「Excel Add-Ins in Python, PyXLL」でテストしたPyXLLを使いました。

from pyxll import xl_func
import rdflib
from rdflib.graph import ConjunctiveGraph, Namespace

@xl_func("int n: var[]")
def testFunc1(n):
	ret = []
	FBNS = Namespace("http://rdf.freebase.com/ns/")
	g = ConjunctiveGraph()
	g.parse("C:\data\sample.n3", format="n3")
	res = g.query("""SELECT ?name ?year WHERE{
		?movie fb:film.film.initial_release_date ?year .
		?movie fb:film.film.starring ?actor .
		?actor fb:type.object.name ?name . }
		order by ?year ?name""", initNs={'fb':FBNS})
	for t in res:
		ls = list(t)
		ret.append(ls)

pyxll.xllファイルを空のシートにドラッグ&ドロップします。
name,yearの2列、検索結果数の6行以上の範囲を指定して、関数を呼びます。
引数は必要ないですが、”1″を指定しています。

sparql1
(注:範囲指定して決定するとき、Ctl-Shift-Enterを忘れずに)

PyXllの環境にrdflibを導入する必要があります。pyxll.cfgにpythonpath=.を指定して、pyxll.xllと同じフォルダにrdflibのフォルダをコピーしました。
(インストールしてからかなりたっているため、具体的なインストール手順は割愛しました。スミマセン。logsフォルダに出力されるエラーを参考にして環境を構築するとうまくできると思います。)

以下が使用したデータです。
書籍にあったものを、抜粋して作りました。
sample.n3

@prefix fb: <http://rdf.freebase.com/ns/> .

<http://rdf.freebase.com/ns/en.hollywood_homicide> 
    <http://rdf.freebase.com/ns/film.film.directed_by> 
    <http://rdf.freebase.com/ns/en.ron_shelton> ;
<http://rdf.freebase.com/ns/film.film.starring> 
    <http://rdf.freebase.com/ns/en.harrison_ford> , 
    <http://rdf.freebase.com/ns/en.kurupt> , 
    <http://rdf.freebase.com/ns/en.robert_wagner> ;
<http://rdf.freebase.com/ns/film.film.initial_release_date> "2003" .

<http://rdf.freebase.com/ns/en.k_19_the_widowmaker> 
    <http://rdf.freebase.com/ns/film.film.directed_by> 
    <http://rdf.freebase.com/ns/en.kathryn_bigelow> ;
<http://rdf.freebase.com/ns/film.film.starring> 
    <http://rdf.freebase.com/ns/en.harrison_ford> , 
    <http://rdf.freebase.com/ns/en.joss_ackland> ;
<http://rdf.freebase.com/ns/film.film.initial_release_date> "2002" .

<http://rdf.freebase.com/ns/en.becoming_dick> 
    <http://rdf.freebase.com/ns/film.film.directed_by> 
    <http://rdf.freebase.com/ns/en.bob_saget> ;
<http://rdf.freebase.com/ns/film.film.starring> 
    <http://rdf.freebase.com/ns/en.robert_wagner> , 
    <http://rdf.freebase.com/ns/en.bob_saget> ;
<http://rdf.freebase.com/ns/film.film.initial_release_date> "2000" .

<http://rdf.freebase.com/ns/en.kurt_russell> 
    <http://rdf.freebase.com/ns/type.object.name> "Kurt Russell" .
<http://rdf.freebase.com/ns/en.bob_saget> 
    <http://rdf.freebase.com/ns/type.object.name> "Bob Saget" .
<http://rdf.freebase.com/ns/en.harrison_ford> 
    <http://rdf.freebase.com/ns/type.object.name> "Harrison Ford" .
<http://rdf.freebase.com/ns/en.robert_wagner> 
    <http://rdf.freebase.com/ns/type.object.name> "Robert Wagner" .
<http://rdf.freebase.com/ns/en.kurupt> 
    <http://rdf.freebase.com/ns/type.object.name> "Kurupt" .

OpenDataはいろんなデータフォーマットがあるので、目的のサンプルデータをつくるのにもう少し調査が必要と感じました。
まずは第一歩としてここまでにしたいと思います。

D3.js from Excel

前回、Excelデータのビジュアライズに、WebViewのバージョンの関係によりD3.jsでなくjqplotを使用しましたが、Selenium IDEを使うと、WebViewでなくWebブラウザを使用できるので、これならD3.jsでもと思い、トライしてみました。

このツールはWebアプリのテスト等に使うもので、ブラウザ操作を自動的にできるなどとても強力なツールです。また各種プログラムコードも出力してくれます。

selenium-vba

https://code.google.com/p/selenium-vba/

ここではVBAからseleniumアドインを組み込んだFirefoxをコントロールする方法でテストしました。これならVBAからFirefoxで表示されているページのJavaScriptを呼び出すことができます。

環境 : SeleniumWrapperSetup-1.0.16.0.exe, Firefox 23.0.1, Excel 2010 / Windows 7
Excel Visual Basic for Application -> ツール -> 参照設定で、SeleniumWrapper Type Library を追加

Private Sub CommandButton1_Click()
   Dim selenium As New SeleniumWrapper.WebDriver
   selenium.Start "firefox", "file:///C:\d3.html"
   selenium.Open "file:///C:\d3.html"
   For i = 1 To 20
       v1 = Sheets(1).Cells(i, 1).Value
       v2 = Sheets(1).Cells(i, 2).Value
       v3 = Sheets(1).Cells(i, 3).Value

       selenium.getEval "setData({'clm1':" + Str(v1) + ", 'clm2':" + Str(v2) + ", 'clm3':" + Str(v3) + "});"
   Next i
   selenium.getEval "plot();"
End Sub

d3_2

D3.jsは以下のサンプルを使いました。

http://bl.ocks.org/mbostock/raw/7586334/

d3_1

サンプルでは、csvからファイルを読み込むようになっていますが、これを以下のように変更しました。
d3.html抜粋

var cars = [];
function setData(d)
{
	cars.push(d);
}
function plot(){
  x.domain(dimensions = d3.keys(cars[0]).filter(function(d) {
    return d != "name" && (y[d] = d3.scale.linear()
        .domain(d3.extent(cars, function(p) { return +p[d]; }))
        .range([h, 0]));
  }));
 .....
}
.....

Firefoxにもアドインを入れておく必要があります。
SeleniumIDE
これはなかなかいいかも。

jQueryPlot from Excel

データビジュアライゼーション。最近とてもブームでもあり私自身も大変興味深い領域です。Excelデータをビジュアライゼーションするとき、どんな形が面白そうかと考えてみたところ、WebでJavaScriptライブラリという結論になりました。Webで表示させるためには、VSTOを使ってWindowsForm上のWebViewにhtmlファイルを読み込ませる方法にしました。もともと今大人気のD3.jsを使いたかったのですが、WebViewがIE7相当のため(Webサーバログで確認)動作しませんでした。対応しないメソッドがあったり、SVGを使うということが原因と思われます。(ちなみにQtのQWebViewでは表示できました。)しかしながら個人的にこのD3.jsを初めて知ったときは、jQueryが登場したときと同じくらい衝撃を受けました。ちょっとはまっています。
そこでD3.jsのかわりにIE7にも対応しているjQueryPlot(http://www.jqplot.com/)を使うことにしました。

前置きが長くなりましたが、ExcelシートにあるデータをWindowFormのボタンを押すとWebViewのグラフが更新されるデモをつくってみました。

jqplot1

jqplotdata1

データを変更(赤字部分)してボタン押下

jqplot2

jqplotdata2

環境 : VisualStudio 2010, Excel 2010 / Windows 7
ThisWorkbook.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;

namespace ExcelWorkbook_Web
{
    public partial class ThisWorkbook
    {
        private void ThisWorkbook_Startup(object sender, System.EventArgs e)
        {
            Form1 fm = new Form1();
            fm.Show();
        }
        public String getData()
        {
            String str = "[";

            for (int i = 1; i <= 7; i++)
            {
                str += "[";

                var o1 = Globals.Sheet1.Cells[i, 2].Value;
                var o2 = Globals.Sheet1.Cells[i, 3].Value;
                var o3 = Globals.Sheet1.Cells[i, 4].Value;

                str += o1.ToString() + "," + o2.ToString() + "," + o3.ToString();
                var o4 = Globals.Sheet1.Cells[i, 1].Value;
                str += ",'" + o4.ToString() + "'";
                str += "]";
                if (i != 7)
                {
                    str += ",";
                }
            }
            str += "]";
            return str;
        }

        private void ThisWorkbook_Shutdown(object sender, System.EventArgs e)
        {
        }

        #region VSTO デザイナーで生成されたコード
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisWorkbook_Startup);
            this.Shutdown += new System.EventHandler(ThisWorkbook_Shutdown);
        }
        #endregion
    }
}

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ExcelWorkbook_Web
{
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            webBrowser1.ObjectForScripting = this;
            webBrowser1.Navigate(new Uri("file:///C:/work/test.html"));

        }

        private void button1_Click(object sender, EventArgs e)
        {
            String str = Globals.ThisWorkbook.getData();
            object[] args = {str};
            webBrowser1.Document.InvokeScript("plot", args);
        }
    }
}

test.html

<html>
<head>
<!--[if lt IE 9]><script language="javascript" type="text/javascript" src="excanvas.js"></script><![endif]-->
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript" src="jquery.jqplot.min.js"></script>
<script type="text/javascript" src="jqplot.bubbleRenderer.min.js"></script>
<link rel="stylesheet" type="text/css" href="jquery.jqplot.min.css" />
<script>
function plot(arg)
{
    var arr = eval(arg);

    plot1 = $.jqplot('chart1',[arr],{
        title: 'Transparent Bubbles',
        seriesDefaults:{
            renderer: $.jqplot.BubbleRenderer,
            rendererOptions: {
                bubbleAlpha: 0.6,
                highlightAlpha: 0.8
            },
            shadow: true,
            shadowAlpha: 0.05
        }
    });
}
</script>
</head>
<body>
<div id="chart1" style="height:300px;width:300px; "></div>
</body>
</html>

Excelシートのデータを変更してボタンを押すと、BubbleChart(というらしい)が変化する模様は、なかなかわかりやすいくて使いやすいと思いました。
いろいろと応用がききそうです。

QtとHaskell/VisualStudio

QtとHaskellは、どちらもソースコンパチブルでクロスプラットフォームの対応ができることから、実行環境について類似点があると思っています。またQtはC++、HaskellはFFI(Foreign Function Interface)によりC言語との親和性がとても高く、長年Cに慣れてきた自分にとって、この二つはとても肌に合う技術です。

JavaVMや.NET(Mono)の中間言語、Python等の軽量言語でクロスプラットフォーム開発をする方法もいいですが、Cでも古くない(やれることが新しい言語に負けていない)という点が魅力に感じます。
QtはUI、Haskellはロジックという使い方で、いろいろやってみたいことがあり、まず最初に、Hakellの関数の戻り値をQWebViewに表示してみることにしました。(WebViewに、ということは、JavaScriptとの連携ができることを意図しています。) QWebviewは以前「QtWebKit.QWebView を使ったPython、JavaScript連携」でテストしましたが、今度はQtがメインでVisualStudioでビルドしました。

環境

Glasgow Haskell Compiler, Version 7.6.3 stage 2 booted by GHC version 7.4.

Qt 5.1.1 for Windows 32-bit
qt-windows-opensource-5.1.1-msvc2010-x86-offline.exe

Visual Studio Add-in 1.2.2 for Qt5
qt-vs-addin-1.2.2-opensource.exe

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"

#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
	ui->webView->load(QUrl("file:///c:/test.html"));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::on_pushButton_1_clicked()
{
  char buf[20];

    HsBegin();
    sprintf_s(buf, "adder : %d", adder(1,2));
    HsEnd();

    ui->webView->page()->mainFrame()->findFirstElement("body").appendInside(buf);
}

Haskellコードは「Haskell from Excel」を参考にしてください。

プログラムを起動するとtest.htmlが読み込まれ、ボタンを押すとエリアに演算結果が追加されます。
実はこのプログラムは、いきなりVisualStudioで作成したのではなく、QtCreator 2.8.1(Baseed on Qt 5.1.1 MSVC 2010.32bit)で作成したものを、Qt5Add-Inを組み込んだVisualStudioで読み込みました。
Qt Creator
QtCreator

Visual Studio Add-in 1.2.2 for Qt5 (Open Qt Project File(.pro))
Qt4AddIn

もちろんQt Creatorだけでも開発可能ですが、Add-InのテストをするためVSを使用しました。
Haskellをメインに、Qtを使うこともできるようですが、私の環境では、ghcで使われているmingwと、Qtで使われるmingwのバージョンが違うせいか、実行時にエラーとなりました。
なかなか思い通りになってくれないものですね。

Hadoop : HDInsight

今話題のWindowsAzureのHadoop、HDInsight。なんとなくわかった気でいますが、実際に以下のサイトを参考に使ってみることにしました。

「HDInsight での Hive の使用」

http://www.windowsazure.com/ja-jp/manage/services/hdinsight/using-hive-with-hdinsight/

HiveとPigは選択できますが、SQLに近いということで、Hiveにしました。
管理ポータルからHDINSIGHTを選び新規に作成します。
hd01

ストレージはアカウントが、東アジアではだめのようですので、アメリカ合衆国西部で新たに作る必要がありました。
HDInsightクラスタの作成まではよかったのですが、参考サイトにある対話型コンソールというものが見当たりませんでした。

「ダッシュボード」の左の雲アイコンをクリックすると、PowerShellを使った使い方が表示されるのでこれを参考にするしかないようです。(JavaScriptを使ったInteractive Consoleが便利そうだったので残念です。)
hd04

Windows Azure PowerShellのインストールには、以下のサイトを参考にしました。

「Install and configure PowerShell for HDInsight」

https://www.windowsazure.com/en-us/manage/services/hdinsight/install-and-configure-powershell-for-hdinsight/?fb=ja-jp

環境 Windows 8.1

WindowsAzurePowerShell.3f.3f.3fnew.exe

Compute Emulator v2.2
Storage Emulator v2.2
Storage Command Line
などがメニューにあらわれた。

Windows Azure HDInsight PowerShell.msi

インストール後、HDinsght関連のPowershellコマンドを表示してみました。

hd03

そして以下のコマンドを実行します。

Get-AzurePublishSettingsFile

ブラウザがたちあがりクレデンシャル情報がダウンロードされます。

Import-AzurePublishSettingsFile C:\Users\\Downloads\-credentials.publishsettings

ダウンロードしたファイルがインポートされます。

Get-AzureSubscription

情報が表示されます。

次に、HDInsightに接続します。

Use-AzureHDInsightCluster xframe (Get-AzureSubscription -Current).SubscriptionId

テストでサンプルデータの検索をしてみます。

Invoke-Hive “select * from hivesampletable limit 10;”

参考サイトにあるような、asv:///でBlobのファイルを読み込ませられるかテストしたかったので、それをPowershellからやってみました。

Invoke-Hive “create table xf01 (t1 string, t2 string, t3 string) row format delimited fields terminated by ‘ ‘;”
Invoke-Hive “load data inpath ‘asv:///example/data/sample.log’ overwrite into table xf01;”
Invoke-Hive “select * from xf01 limit 10;”

なぜか、もともとdata/sample.logにあったのですが、hive/warehouse/xf01/sample.logに移動させれられました。

Azure Storage Explorer
StoregeExp01
しかしJavaScriptコンソールはどこに行ってしまったのか、これがないと本当に不便です。あとコマンドを発行してから結果が返るまでかなり遅いのも気になります。(私の環境だけかもしれませんが・・)

とりあえず、使ったみました。

Apps for Office

VisualStudio 2013のプロジェクトテンプレートに、Office 2013用アプリというテンプレートがC#の下にあります。
これを以下のサイトを参考に、Apps for Officeをつくってみました。(Excel)

How to: Create your first task pane or content app by using Visual Studio

http://msdn.microsoft.com/library/office/fp142161%28v=office.15%29

その前に、これに取り組もうと思ったのは、なんとJavaScriptでExcelのCellを読み書きできてしまうからです。どのように使うものなのかということより、まずこれを試したかったからです。
(しかしいつもネーミングが汎用的でわかりづらいですね。(ストアアプリとかも) 日本語だとOfficeアプリ? Office Web Appsと似ている・・など、もう少し機能が明確化できる名前だといいのですが。)

Office用アプリの作成で、「Excelのコンテンツアプリ」を選びました。参考サイトとは違うのですが、作業ウィンドウという特別なところにおかれるのではなく、画像やグラフのように任意の場所に置きたかったからです。
oa1

環境 VisualStudio 2013, Office 2013 / Windows 8.1
Home.js

(function () {
    "use strict";
    Office.initialize = function (reason) {
        $(document).ready(function () {
            app.initialize();

            $('#btnWrite').click(writeText);
            $('#btnRead').click(readText);
        });
    };
    function writeText() {
        Office.context.document.setSelectedDataAsync($('#wtest').text(),
            function (asyncResult) {
                if (asyncResult.status === "failed") {
                    $('#result').text(asyncResult.error.message);
                }
            }
        )
    }
    function readText() {
        Office.context.document.getSelectedDataAsync("matrix",
            function (asyncResult) {
                if (asyncResult.status === "failed") {
                    $('#result').text(asyncResult.error.message);
                }
                else {
                    $('#rtest').text(asyncResult.value);
                }
            }
        );
    }
})();

Home.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=Edge" />
    <title></title>
    <script src="../../Scripts/jquery-1.9.1.js" type="text/javascript"></script>

    <link href="../../Content/Office.css" rel="stylesheet" type="text/css" />
    <script src="https://appsforoffice.microsoft.com/lib/1.0/hosted/office.js" type="text/javascript"></script>

    <link href="../App.css" rel="stylesheet" type="text/css" />
    <script src="../App.js" type="text/javascript"></script>
    <script src="../Visualization.js" type="text/javascript"></script>

    <link href="Home.css" rel="stylesheet" type="text/css" />
    <script src="Home.js" type="text/javascript"></script>
</head>
<body>
    <center><h3>Apps for Office Test</h3></center>
    <button id="btnWrite">Write Text</button>
    <button id="btnRead">Read Text</button>
    <div id="wtest">123456789</div>
    <div id="rtest">---</div>
    <hr />
    <div id="result">message : </div>
</body>
</html>

デフォルトでjQueryサポートです。最近つかいまくってますね。またC#のプロジェクトなのにC#はどこにもでてきません。

初期画面
oa2

‘Write Text’をクリック(表示領域をあらかじめ選択してからも可。コードを変更して配列を書き込むことも可)
そして選択箇所そのままで’Read Text’をクリック
oa3

値を入力後、範囲を指定して’Read Text’をクリック
oa4

範囲を指定して’Write Text’をクリック
oa5
配列を書き込むようにしていないのでエラー

オフラインローカルのExcelファイルとしては使えないみたいですが(まだ調査不足ですが)、それがちょっと残念です。(ExcelシートにWebViewが埋め込まれ、相互データ連携ができると、Webの柔軟性からかなり用途が広がるのですが)
でもなかなか面白い機能です。

(追記:2014/09/27)SharePointに登録して、Officeアプリとして挿入が可能。

Haskell from Excel

HaskellのモジュールをExcelから呼び出す方法がかかれたBlogをみつけたので、実際に自分の環境でやってみました。

Calling Haskell from Excel

http://flxldn.tumblr.com/post/163596541/calling-haskell-from-excel

しかし環境が違うためか、残念ながらできませんでした。せっかくなので覚えとして書きたいと思います。
(いろいろやってみてXLLアドインの勉強にはありましたが・・)

C++からHaskellの呼び出し、ExcelからのC++(XLL)呼び出しはできますが、つなげると以下のようなアラートがでました。
xllError
XLLは、xlw(A Wrapper for the Excel API)を使う方法と、Excel 2010 XLL SDKを使う方法と、二通りやりました。

参考)
xlw :

http://xlw.sourceforge.net/

http://d.hatena.ne.jp/teramonagi/20110124/1295866787

xll sdk:

http://www.microsoft.com/en-us/download/details.aspx?id=20199

テスト環境 Excel 2010 + xlw ver5, Visual Studio 2010 / Windows 7

まずHaskellソースからDLLを作成します。
addr.hs

module Adder where 

adder :: Int -> Int -> IO Int --gratuitous use of IO 
adder x y = return (x+y) 

foreign export stdcall adder :: Int -> Int -> IO Int

adder.h

#ifdef __cplusplus
extern “C”
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif

adder.def

LIBRARY Adder
EXPORTS
adder@8=_adder
HsBegin@0=_HsBegin
HsEnd@0=_HsEnd

dllMain.c

static char* args[] = {"ghcDll" , NULL };

BOOL STDCALL DllMain( HANDLE hModule, DWORD reason, void* reserved)
{  return TRUE;}
__stdcall void HsBegin()
{
startupHaskell(1, args, __stginit_Adder);
}
__stdcall void HsEnd()
{
hs_exit();
}

以下コンパイル手順です。(VisualStudio2010コマンドプロンプト)

ghc -static -c adder.hs -fglasgow-exts
ghc -static -c dllMain.c
ghc -static -shared -o adder.dll adder.o adder_stub.o dllMain.o
lib /MACHINE:x86 /DEF:adder.def /OUT:adder.lib /NOLOGO /SUBSYSTEM:WINDOWS

出力されたadder.dllはSystem32フォルダにコピーします。

次に、XLLファイルを作成します。
xlwのインストールディレクトリの中にあるxlwTemplateExtractor.exe実行すると、XLL_Projectというフォルダがマイドキュメントに作成されるので、ここにあるソリューションを開きます。
デフォルトのEchoShortの下に追加して以下のようになります。

#include<cppinterface.h>

#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif

#pragma warning (disable : 4996)

short // echoes a short
EchoShort(short x // number to be echoed
           )
{
    return x;
}

short funcAdd(short d1, short d2){
 return adder(d1, d2);
//return d1 + d2;
}

cppinterface.hにはfuncAddのプロトタイプを追加します。
xlwWrapper.cppというソースは自動で生成されるようです。
adder.libを参照するようにします。

まずコメントしてあるd1+d2で成功したことを確認してから、adderのテストしました。
すると上記アラートがでます。
ここで、HsBegin、HsEndを使い方を元のブログを見てみると、ライブラリ自体のmakeが必要のようだったのであきらめ、次にXLL SDKをテストしました。(ライブラリを変更してもたぶん結果は同じという気もしましたし)

XLL SDKをインストールしたフォルダ内にある、EXAMPLEプロジェクトを使用します。
他の関数を参考にして、


#define rgFuncsRows 30

static LPWSTR rgFuncs[rgFuncsRows][7] = {

....
	{L"CalcCircum",					L"BB", L"CalcCircum"},
	{L"funcAdd",					L"III", L"funcAdd"}
};

....
__declspec(dllexport) double WINAPI CalcCircum(double pdRadius)
{
	return pdRadius * 6.283185308;
}
__declspec(dllexport) short WINAPI funcAdd(short x, short y)
{
	return (short)adder((long)x,(long)y);
	//return x + y;
}

このソースのxAutoOpen()、xAutoClose()にそれぞれHsBegin()、HsEnd()を追加。これらとadderの宣言部もxlwと同様に追加。

これもreturn x+yで動作確認後、Haskell呼び出し部をテストしました。それで上記アラートが出ました。
Excel-DNAてadder.dllを、とも思いましたが、あれはマネージDLLでした。
成果が何もないのもなんなので、cppコンソールアプリでHaskell呼び出しをしてみました。(adder.dllはexeと同じところに置く)

#include "stdafx.h"

#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif

int _tmain(int argc, _TCHAR* argv[])
{
	HsBegin();
	printf("adder : %d\n", adder(1,2));	
	HsEnd();	
	getchar();
	return 0;
}

3 を表示します。

また解決したらつづきを書きたいと思います。

C# – IronPython データ連携

C#とIronPythonを連携させようと思ったのは、Pythonの数値計算ライブラリNumPyがIronPythonでもインストールできるというサイトを見つけたからです。(また、VSTOでExcelのデータ処理にも使えればと)

https://www.enthought.com/repo/.iron/

これを使って、C#、IronPython間のデータの受け渡しテストをしてみました。

環境 : IronPython 2.7.3 (2.7.0.40) on .NET 4.0.30319.296 (32-bit), Visual Studio 2010 / Windows 7

インストール
1)ironpkg-1.0.0.pyをダウンロード
2)以下コマンド実行

ipy ironpkg-1.0.0.py –install
ironpkg scipy
ipy -X:Frames -c “import scipy”

いろいろと調べてトライしましたが、残念ながらSciPyは使えないようです。しかしNumPyは使えるので、こちらだけ使いました。
(NumPyだけできるものにしました)

csTest.py

import sys
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7')
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\DLLs')
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib')
sys.path.append(r'C:\Program Files (x86)\IronPython 2.7\Lib\site-packages')

import clr
clr.AddReference('mtrand.dll')

import numpy as np

na = np.zeros(shape=(2,2))

for i in range(2):
	for j in range(2):		
		na[i, j] = mx[i, j]

mr = np.linalg.inv(na)
print '- Iron Python -'
print mr
print np.dot(na, mr)

for i in range(2):
	for j in range(2):
		mx[i, j] = float(mr[i, j])

C#で設定した2次元配列のデータをNumPyを使って逆行列の計算をして戻すというものです。
しかしC#の配列からのNumPy配列に渡す(その逆も)やり方ついていろいろと悩みました。
mxのままだと逆行列を求める関数でエラーをだしました。(np.array(mx)とやるときは、mxはジャグ配列([][])でないといけないみたいだし・・)
結果代入という形にしてしまいましたが、もっといい方法がないかまた調べたいと思います。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System.Collections;
using IronPython.Runtime;

namespace csPyTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var pe = Python.CreateEngine();           
            ScriptSource src = pe.CreateScriptSourceFromFile(@"C:\csTest.py");
            ScriptScope scope = pe.CreateScope();

            double[,] mx = new double[,] {{0,1},{2,3}};
            scope.SetVariable("mx", mx);

            src.Execute(scope);

            var m = scope.GetVariable<double[,]>("mx");

            Console.WriteLine(" - C# - ");
            for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 2; j++)
                {
                    Console.Write(m[i, j] + " ");
                }
                Console.WriteLine();
            }
            Console.ReadLine();
        }
    }
}

C#からダイナミック言語のPythonの変数に直接アクセスできるのも、強力な機能ですね。しかしもうすこしCPythonのライブラリが使えるようになってほしいところです。

以下は実行結果です。逆行列の確認として、単位行列を出力しています。
NumPy

Pyvot / Excel

Excelネタが続きますが、今回はPythonを使ったExcel操作です。Excel「ファイル」への読み書きを目的にしたものではなく、開いたままのシートに対してリアルタイムに読み書きするものです。Pythonはソースを見やすいようにパッケージの形にしましたが、コンソールでの操作を想定しています。
コンソール画面でプログラムのテストしたりするときに、標準入力や標準出力をセルでやると面白いかもということで試してみました。WindowsやLinuxなどのコマンドラインでデータの入出力をするときなど、ファイルでもいいのですが、データを部分的に変更したりするとき、この方法は便利です。視覚的にもわかりやすいです。(こんな用途かぎられるかもしれませんが・・)

環境 : Python 2.7.3, Excel 2010 / Windows 7
インストール :

http://pytools.codeplex.com/wikipage?title=Pyvot

PTVSからもできるようですが、よくわかりませんでしたので、

https://pypi.python.org/pypi/Pyvot

こちらのサイトから
Pyvot-0.1.2-py2.7.egg
をダウンロードして、easy_install コマンドを使いました。
あとwin32comも必要です。

使い方に関しては、以下の動画がわかりやすかったです。

基本的な機能を使ってみました。
pyvot_1
Pythonから書き込んだあと、Excelシートをエディトして(1 -> 10)、Excelから読みこみます。(w.get())
Pyvot_2
これを踏まえて、ちょっと変わった使い方ですが連続してデータをExcelに送り、グラフを表示してみました。

import xl
import threading
import time
import random

def main():
	xl.Workbook('xlTest.xlsx')
	
	r = range(1,11)
	for i in range(10):
		xl.get("A1:A10").set(r)
		random.shuffle(r)
		time.sleep(1)

if __name__ == '__main__':
	main()


初期値は以下で、
PYvot_3
あとは1秒ごとにランダムに並び順が変化します。
Pyvot_4
実は、マルチスレッドでデータを変化させ、リアルタイム解析みたいなことができないか、ということをしたかったのですが、Pythonのスレッドの中からxl関数を呼び出すと、エラーになってしまいました。また前提条件として、プログラム動作中、セルをクリックすると停止します。あと変更対象のセルにはあらかじめデータを入れておく必要があります。
自分が個人的にやりたかったことができないものもありましたが、十分使えるツールだと思います。

また、いろいろと試していきたいと思います。

Excel と R via VSTO

RExcelアドインを使ってExcelとR連携は前々回テストしましたが、VSTOを使ってRを呼び出すテストをしてみました。
これには、“C#, Python で R.NET”でテストしたR.NETを使います。
プロジェクトは“LINQ/VSTO”と同じ方法で作成します。

環境: Excel2010, R 3.0.0 / Windows 7
VisualStudio 2010 参照設定追加
RDotNet
RDotNet.NativeLibrary

using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using RDotNet;
using Excel = Microsoft.Office.Interop.Excel;

namespace ExcelWorkbook3
{
    public partial class Sheet1
    {
        private void InternalStartup()
        {
            DataTable table = new DataTable();
            Excel.Worksheet activeSheet = ((Excel.Worksheet)Application.ActiveSheet);

            var envPath = Environment.GetEnvironmentVariable("PATH");
            var rBinPath = @"C:\Program Files\R\R-3.0.0\bin\i386";
            Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + rBinPath);
            using (REngine engine = REngine.CreateInstance("RDotNet"))
            {
                engine.Initialize();

                StringBuilder plotCommmand = new StringBuilder();  
                plotCommmand.Append(@"rnorm(100)");
                var e = engine.Evaluate(plotCommmand.ToString());
                int k = 1;
                foreach (var v in e.AsNumeric().ToArray<double>())
                {
                    activeSheet.Cells[k, 1].Value = v;
                    k++;
                }
            }
        }
    }
}

R側では正規分布の乱数を生成するrnorm関数を使い、その出力をExcelシートに表示させます。Excel側では、グラフ表示をして正規分布を確認しました。(手動)
(ちなみにRのPlotを呼び出すこともできます)
R_VSTO1
このような単純な例では、どんな連携方法も大差ありませんが、その他に組み合わせるものがある場合、いろいろと解決方法を知っておくと便利です。

Excel Add-Ins in Python, PyXLL

前々回の投稿のExcel-DNAのホームページを見ていると、PythonでExcelと連携するPyXLLというものの存在をしりました。
Pythonが主でExcelシートを操作できるライブラリもありますが、Excelが主でPythonをバックエンドで使えるというメリットは、それ以上の広がりがあると思いテストしてみました。

環境 : PyXLL ver2.0.4, Excel 2010 / Windows 7
Download : http://www.pyxll.com/index.html

from pyxll import xl_func

@xl_func("var[] nnn: var[]")
def testFunc1(nnn):
	res = []
	for nn in nnn:
		r = []
		for n in nn:
			n = n * n
			r.append(n)
		res.append(r)
	return res
	

元のマトリックスの要素を自乗します。
pyxll1

Excel-DNAのときと同様、この状態で CTL + SHIFT + Enter を押します。

pyxll2

Excel-DNAの手軽さでPythonが使える、それだけでも魅力ですが、データ操作をPythonでできるというのは、生産性が高くなります。

Excel と R

前回に引き続きExcelと外部ツールの連携についての調査で、フリーの統計解析ツールとして有名なRを試してみました。
Rは以前R.NETの話題で投稿しましたが、とても強力なツールで時々使用しています。解析という点では、Excelだけで十分なことも多いのですが、作業環境といった点で使い分けるメリットは大きいと思っています。
連携ツールには、RExcelというアドインを使いました。

環境 : R version 3.0.0, Excel 2010 / Windows 7

1) 以下をインストールします
RExcel_3.2.13
statconnDCOM3.5-1B2_Noncommercial

2) Rでは、
rscproxy
rcom
をインストールします

http://rcom.univie.ac.at/download.html

3) ExcelのオプションからアドインRExcel2007を組み込みます
使用するExcelは2010ですが、これでも動作しました。(たまにエラーがでて不安定な気もしますが、一応動いています)

参考) http://d.hatena.ne.jp/Rion778/20091012/1255362015

これで、プレゼンテーションはExcel、バックグランドはRといった使い分けをした例をつくってみました。
RExcel5
RExcel7
テストの意図は、データスライダーでデータの分布をリアルタイムに変更させたものをRでデータと回帰分析結果をグラフ表示するといったものです。
回帰分析自体はExcelだけでもできますが、わかりやすい例ということでRでやってみました。
興味深い点は、以下のRのソースをエクセルで記述して、範囲指定して関数定義できます。それをRApply関数を通して実行できます。

function(x,y,L){
  xy <- data.frame(x=x,y=y)
  xy.lm <- lm(x~y,data=xy)
  plot(x, type="l",xlim=c(0,16),ylim=c(0,L),col="green",lwd=1)
  par(new=T)
  plot(y, xlim=c(0,16), ylim=c(0,L), col="red", pch=3)
  abline(xy.lm, col="blue", lwd=2)
}

これも含めて、いくつかのわかりやすいデモが用意されています。
RMenu1
今回はわざわざスライダーやブロットという見た目わかりやすいものを使いましたが、ExcelシートのデータをRにデータフレームという形で渡し、Rで演算した結果を地味にExcelに戻すというのは使えるのではと思いました。
RではExcelにないライブラリを使えるのも魅力ですが、Matlabのようにマトリックス演算を使って自前でいろいろプログラミングできるのは面白そうです。
最近このジャンルには、いろんな可能性を感じているため鋭意調査・勉強中ですが、やりたいことがたくさんあるのに時間が不足している状況です。少しづづ整理して、またまとめていきたいと思っています。

しかしながら、ExcelとRの書籍を比べてみると、Excelはカラーで数も多く価格も安い反面Rはそれとは逆の傾向にありますね。当然といえば当然ですが、通常の業務を考えてみてもExcelの普及率、利用率の高さにはとても驚かされる次第です。(仕様書読んだり作成したりとか多いですが・・)

Excel-DNA

Excelと外部ツールが連携できるものをいろいろと調べていたら、Excel-DNAというものが面白そうだったので試してみました。
ver 0.30 (Wed Dec 12, 2012 at 4:00 PM)

http://exceldna.codeplex.com/

また以下サイトに大変詳しく説明されています。

http://supermab.com/wp/

今回これを参考にさせていただきました。

ExcelDna-0.30を上記サイトからダウンロードしDistributionフォルダの以下のファイルをワークフォルダにコピーします。
ExcelDna.dna
ExcelDna.xll
この二つのファイルは同じフォルダに置き、拡張子以外のファイル名は変更してもいいですが同じものにします。
編集するのは.dnaファイルのみで.xllファイルはExcelへのインポート(ドラッグ&ドロップまたはアドイン追加)に使用します。

ExcelDna.dna

<![CDATA[
using System;
using System.Numerics;

public class Test
{
	public static object [] TestArray(int n)
	{
		int x = 10;
		object [] arr = new object[x];

		for(int i=0;i<x;i++){
 			arr[i] = n + i;
 		}
 		return arr;
 	} 
} 
]]>

C#のソースをコンパイルをすることなく、テキストエディタで編集するだけというのがとても手軽です。
そしてこれだけで、なんとTestArry()がユーザ定義関数として、Excelで利用できます。ちょっと驚きです。

私がやりたかった「ユーザ関数から配列を返した結果を複数のセルに表示させる」ことにはちょっと戸惑いました。
そもそもExcelの配列数式なるものを知らなかったためです。
あと、配列をint[]で返すとExcelから見えないようです。エラーをださないので原因がわかりませんでした。

以下に手順をメモしておきたいと思います。

excelDna1
上のような状態で、CTRL + SHIFT + Enter を押します。セルは複数選択しておく必要があります。
選択したセルが一つだったり、Enterキーだけ押した場合は、一つのセルにしか表示しません。
excelDna2
無事表示できました。^^;
個人的にはVSTOが好きですが、この手軽さはとても魅力に思いました。

Azure Storage Explorer & SharpDevelop

前々回のAzure Table Storage、前回のメタプログラミングの投稿で、補足しておきたいことがありましたので、ここにまとめて書きたいと思います。
Azure Table Storageは、LINQPad以外にも、Azure Storage Explorerという便利なツールがあったのでこれでもテストしてみました。

ver 4.0.0.10 (05.07.2011)

http://azurestorageexplorer.codeplex.com

AzureStorageExplorer1

ShapDevelopは、Boo言語が標準で対応しているのですね。以下のようにC#からコードがコンバートすることもできます。

ver 4.3.3 Build 9663 (.NET 4.0.30319.296)

http://sharpdevelop.codeplex.com/

sharpDevelop1
sharpDevelop2
sharpDevelop3
逆はできないようです。
ツールのメモでした。。

メタプログラミング.NET

Windowsストアアプリの開発をしていたところ、Windows8.1環境が複数いることになり、ちょっと心が折れてしまいました。来月正式版がでるようなので、それを待って再開したいと思います。

それもあり、ASCIIから出たタイトルと同名の本に興味深い内容があったのでテストしてみました。
メタプログラムという、プログラムをプログラムする機能を使って、一つのコードから複数の.NET言語コードを生成してみました。
C++/CLI, C#, VB.NETの出力ができることを確認しましたが、それだけではつまらないと思い、VJ#とかやってみようと思いましたが、どうやら最近のVisualStdudioでは対応していないようです。F#も対応していないようです。
そして、本を読み進めていくとBooという言語があることを知りました。Mono(.NET互換環境)とかでよく使われているPythonに似た言語ということで、面白そうなのでこれを出力する方法調べてみました。

https://github.com/bamboo/boo にある、bin/Boo.Lang.CodeDom.dll をダウンロードして参照に追加します。
環境 : VisualStudio 2010 / Windows 7

using System;
using System.IO;
using System.Text;
using System.CodeDom;
using System.Diagnostics;
using System.CodeDom.Compiler;

class TestCodeDOM
{
    static void Main()
    {
        CodeNamespace prgNamespace = BuildProgram();
        var compilerOptions = new CodeGeneratorOptions()
        {
            IndentString = "  ",
            BracingStyle = "C",
            BlankLinesBetweenMembers = false
        };
        var codeText = new StringBuilder();
        using (var codeWriter = new StringWriter(codeText))
        {
            CodeDomProvider provider = new Boo.Lang.CodeDom.BooCodeProvider();

            ICodeGenerator gen = provider.CreateGenerator();
            CodeGeneratorOptions options = new CodeGeneratorOptions();
            gen.GenerateCodeFromNamespace(prgNamespace, codeWriter, compilerOptions);
        }
        Console.WriteLine(codeText.ToString());
        Console.ReadLine();
    }
    static CodeNamespace BuildProgram()
    {
        var ns = new CodeNamespace("TestCode");
        var systemImport = new CodeNamespaceImport("System");
        ns.Imports.Add(systemImport);
        var programClass = new CodeTypeDeclaration("Program");
        ns.Types.Add(programClass);
        var methodMain = new CodeMemberMethod
        {
            Attributes = MemberAttributes.Static,
            Name = "Main"
        };
        methodMain.Statements.Add(
          new CodeMethodInvokeExpression(
            new CodeSnippetExpression("Console"),
            "WriteLine",
            new CodePrimitiveExpression("Hello world")
          )
        );
        programClass.Members.Add(methodMain);
        return ns;
    }
}

これを実行すると以下のようなコードを出力します。

namespace TestCode
import System

class Program:
static def Main():
Console.WriteLine(“Hello world”)

言語プロバイダの部分を変更すると、VBやC#、C++も出力することができます。

CodeDomProvider provider = CodeDomProvider.CreateProvider("cpp");

.NETはいろんなことできるものですね。
ちょっと禁断の領域に足を踏み入れたかも・・


#
C#
Tags:

Azure Table Storage / LINQPad

LINQPadAzure

LINQPadを使う機会があったので、ついでに以前、WindowsAzure Storage Python ライブラリの投稿でテストした、Azure Table StorageをLINQPadからアクセスしてみました。

http://blog.madd0.com/2012/01/09/linqpad-driver-for-azure-table-storage/

このサイトにある、TableStorageのドライバーのcompiled and packaged を入手して、LINQPadにDriver(Madd0.AzureStorageDriver-v1.0.0-beta.lpx)をインポートします。
(Add connection -> View more drivers -> Browse..)

ドライバーのおかげで簡単にアクセスできるようになりました。

環境: LINQPad Free Edition 4.45.05 / Windows 7

このようなちょっとしたテストをBlogに残すって結構便利なんですよね。Pythonで以前やったテストも、Blogを参考にして再テストしたりしましたし、日付や前後の記事からいつごろどういった背景でやったテストかがわかったりと、自分自身に役立ちます。ツールのバージョンやインターフェイスが変わって現在では同様のテストができなくても(とくにサービスからみとか)、エビデンスとして残っていると、どこまでできたかがよくわかります。

と、つくづく思ったテストでした。

Windows Store App で音声合成

Windowsストアアプリを開発中ですが、Windows 8.1から Windows.Media.SpeechSynthesis が新たに加わるようです。これでテキストの音声読み上げができるようになったということで試してみました。

http://msdn.microsoft.com/en-us/library/windows/apps/windows.media.speechsynthesis.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1

環境 : VisualStudio 2013 Preview / Windows 8.1 Preview / VirtualBox 4.2.16 / Mac OS X 10.7.5

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Media.SpeechSynthesis;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace csStoreXaml1
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void Button_Click(object sender, RoutedEventArgs e)
        {

            // The media object for controlling and playing audio.
            MediaElement mediaElement = new MediaElement();

            // The object for controlling the speech synthesis engine (voice).
            var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();

            // Generate the audio stream from plain text.
            SpeechSynthesisStream stream = await synth.SynthesizeTextToStreamAsync("クロスフレーム in 愛知県名古屋市");

            // Send the stream to the media object.
            mediaElement.SetSource(stream, stream.ContentType);
            mediaElement.Play();

        }
    }
}

日本語にも対応しているのは嬉しいことです。「愛知県名古屋市」も問題なく聞き取れました。
ストアアプリの新しい企画を考える際、幅が広がりそうです。

C#, Lua連携

Luaという汎用スクリプト言語ですが、最近いろんなところで目にするようになりました。ネットワークツールのNmap、インメモリDBのRedis、Vocaloidやゲームなど、幅広いところで使われています。VisualStudioのNuGetにもSharpLuaというパッケージがあったので、これを使ってC#との相互呼び出しをやってみようと思いました。
しかし、C#からはLuaを使えるのですが、その逆がうまくいかなかったので、LuaInterface(http://code.google.com/p/luainterface/)というものを使いました。

環境 : VisualStudio 2010 / Windows 7
C#コンソールアプリケーション


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LuaInterface;
using System.Reflection;

namespace csConsLua
{
    class Program
    {
        LuaInterface.Lua lua = new LuaInterface.Lua();

        static void Main(string[] args)
        {
            Program p = new Program();

            p.start();

            Console.ReadLine();
        }
        public void csFunc(string msg)
        {
            Console.WriteLine("msg : " + msg);
        }
        public void start()
        {
            lua.DoString("function luaFunc(msg) return string.format(\"msg : %s\", msg) end");

            object[] o = this.lua.GetFunction("luaFunc").Call("from C#");
            string s = (string)o[0];

            Console.WriteLine(s);
            
            lua.RegisterFunction("csFunc", this, GetType().GetMethod("csFunc"));

            lua.DoString("csFunc(\"from Lua\")");

        }
    }
}

設定としては、http://luainterface.googlecode.com/files/LuaInterface_2.0.3.7z を解凍してできたdllを、「参照の追加」で読み込み、プロジェクトのプロパティで、「対象のフレームワーク」を ‘.Net Framework 3.5 Client Profile’ にしました。
これを実行した出力は、

msg : from C#
msg : from Lua

となります。
また、統合開発環境には、ZeroBraneStudio(https://github.com/pkulchenko/ZeroBraneStudio)というものがあり、学習に便利だと思いました。

次は、Redis/Azureあたりをやってみたいと思っています。

Haskell / Windows

Haskellは以前勉強しましたが、使うことがないこともあってまったく身に付きませんでした。関数型言語はF#を学習中ですが、いろいろと勉強しているとHaskellに関するサンプルや情報が多いことを感じ、すぐテストできる環境を用意しておいた方がいいと思い、セットアップしてみました。

http://neue.cc/2010/01/04_233.html

このサイトをみると、IDEにはLeksahがよさそうだ、ということでインストールしてみました。
Leksahの前に、Haskell Platformをインストールする必要があります。
HaskellコンパイラGHCのバージョンは、7.6.3ですが、leksah-0.12.0.3-ghc-7.4.1.exe(これが最新なので)を使いました。

Leksahを起動後、Package->Newから、Create Folderでフォルダを作りますが、これがイコールプロジェクト名となります。フォルダを作成してOpenすると、Package設定がでてくるので、Executablesを選択して、ExecutableNameをクリックしてSaveします。
Lekp

デフォルトで以下のような、”Hello World”を表示するだけのサンプルコードが生成されるので、これを
- Configures the package
- Builds the package
- Runs the package
と順に、ツールバーから実行します。するとLog Windowに”Hello World”が表示されます。
hcode

これでとりあえず動作確認をしておいて、目的のプログラムを動かしてみます。
ファイルコンバータ的なものをつくることが多くなりそうなので、大文字変換するものを試してみました。
Lek0s
あとエディタの面白い機能として、カスタム文字への変換があります。
Configuration->To Candyチェックボックスで、以下の表示切替をできます。

Lek1s

Lek2s

こういうのマニア心をくすぐりますね。ソースは、O’REILLYの”Real World Haskell”から引用しました。
欲を言えば、neueccさんのサイトにあるVisual Haskellのようなものが使えれば、とも期待もしたのですが(VisualStudioで他の言語とリンクできたりできるなどなど)、無理っほいのでここまでとなりました。

Python / Django / WindowsAzure

Pythonの代表的なWebアプリケーションフレームワークであるDjangoをWindowsAzureにデプロイしてみました。
各ツールのバージョンか変わるとセットアップの方法も変わったりしますので、最新のものでテストしてみました。

環境 : VisualStudio 2013 Preview / Windows 8.1 Preview / VirtualBox 4.2.16 / Mac OS X 10.7.5

参考サイト : One of Microsoft’s Best-Kept Secrets – Python Tools for Visual Studio (PTVS) http://www.hanselman.com/blog/OneOfMicrosoftsBestKeptSecretsPythonToolsForVisualStudioPTVS.aspx

プロジェクトの新規作成からPython -> Django Application を選択
ソリューションエクスプローラから、PythonEnvironments右クリック -> Add Virtual Environment

pyvenv

env(Pyton3.3)右クリック->Install Python Package

dangoInst

インストールが無事終了したら、まずはローカルサーバで確認するためInternet Explorer で実行
以下のような画面が表示されます。

djangoApp

WindowsAzureへのデプロイは、前回のSignalRの記事と同様に発行プロファイルをダウンロードしてVisualStudioにインポートします。

http://(作成したWEBサイト).azurewebsites.net/

で、ローカルで確認した同じページが表示されます。

以前違う方法でトライして失敗したためそのままにしていましたが、バージョンが上がって、かなり簡単にDjangoのインストールができるようになりました。

とりあえずここまでメモということで。

SignalR / WindowsAzure

前々回の投稿「ASP.NET SignalR」で、SignalRのテストをIISでしましたが、これをAzureにデプロイしてみたのを備忘録として書きました。

1) manage.windowsazure.comのサイトで、WEBサイトを新規追加
2) ダッシュボードの概要から、発行プロファイルのダウンロード
azureWeb
3) VisualStudo2012のプロジェクト右クリックで、「発行」を選択
4) 2)でダウンロードしたプロファイルをインポート
azureDeploy
インポートをすると自動的に上のような画面になります。
5) 「発行」ボタン押下でブラウザが起動 URL http://****.azurewebsites.net
6) URLをhttp://****.azurewebsites.net/WebFrom1.aspx

これで動作確認できました。

ソースは以下の部分修正しました。

//var connection = $.hubConnection("http://192.168.11.10/test/aspEmptyWebSignalr/signalr/hubs");
var connection = $.hubConnection();

(こういうのメモしておかないと、バージョンアップ等でインターフェイスとか変わったりすると結構つまらないところで悩んだりするんですよね。)

ブラウザは、IE10とFireFoxで試しましたが、WebSocketの通信ではなく、JSONのようでした。AzureのサーバがWebSocket対応でないためでしょうか。

Windowsストアアプリ申請

二つ目のWindowsストアアプリを本日申請しました。前回のリリースでBlogに書きませんでしたので、ストアアプリの開発の方針みたいなものをまとめてみました。

ストアアプリは従来のWindowsアプリケーションとは、大きく様変わりしているので、いろいろとテストをしています。しかしやはり何か目的があった方(形になった方)がより開発のモチベーションもあがるということで、いろんなタイプのアプリケーションを作っていこうと思っています。いまのところの目標は、WindowsAzureとこれからリリースされるであろうWindowsPhone8で何かやってみたいと思っています。

ストアアプリはいろんな言語で開発できますので、いろいろと試す意味でも前回は、JavaScript + SVG、今回はC# + XAMLで開発しました。こんなことを繰り返しながら目標に近づいていけたらと思っています。

リリース済 Clocklavier ピアノで時刻を奏でます icon
申請中 bitlife ライフゲームに編集、保存、サウンド機能を追加してみました StoreLogo
開発中 メッセージアプリ(仮) ローカルネットワークのチャットアプリです。

ストアアプリの情報は、以下サイトをご覧ください。

./apps/

個人的趣味が強いですが、よろしかったお試しくたざいませ。

ASP.NET SignalR

サーバプッシュのWebテクノロジーはいくつかありますが、ASP.NETで提供される最新の技術であるSignalRを試してみました。
最近いろいろとテストするにあたって感じるのは、記事等を読んで理屈ではわかっていても実際にやってみると環境や設定、バージョン違い等で構築に結構手間取ったりすることがあります。やはり実際に自分でやってみるということは大切だと思うこのごろです。

今回参考にしたのは以下の記事ですが、パケットキャプチャをとるためIIS(ローカル)で動作させました。
http://www.atmarkit.co.jp/ait/articles/1303/19/news099.html ASP.NET SignalR入門(前編)

環境 : VisualStduo 2012 / Windows 8

管理者としてVSを実行
ASP.NET空のWebアプリケーションのプロジェクトを作成
参照設定の追加でNugetパッケージ管理からSignalRを検索してインストール
新しい項目の追加でSignalR Hubクラスを作成 MyHub1.cs
新しい項目の追加でグローバルアプリケーションクラス作成 Global.asax
新しいウェブフォームの追加 WebForm1.aspx, WebForm2.aspx

MyHub1.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using Microsoft.AspNet.SignalR.Hubs;

namespace aspEmptyWebSignalr.Hubs
{
    [HubName("echo")]
    public class MyHub1 : Hub
    {
        public void Send(string text)
        {
            Clients.All.Receive(text);
        }
    }
}

Global.asax

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;

namespace aspEmptyWebSignalr
{
    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            RouteTable.Routes.MapHubs();
        }
    }
}

WebForm1.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="aspEmptyWebSignalr.WebForm1" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
  <script src="Scripts/jquery-1.6.4.min.js"></script>
  <script src="Scripts/jquery.signalR-1.1.2.min.js"></script>
  <script>
      $(function () {
          var connection = $.hubConnection("http://192.168.11.10/test/aspEmptyWebSignalr/signalr/hubs");
          var echo = connection.createHubProxy("echo");
          echo.on("Receive", function (text) {
              $("#list").append("<li>" + text + "</li>");
          });
          $("#send").click(function () {
              var message = $("#message").val();
              echo.invoke("Send", message).done(function () {
                  $("#message").val("");
              });
          });
          connection.start(function () {
              $("#send").prop("disabled", false);
          });
      })
  </script>
</head>
<body>
  <form id="form1" runat="server">
  <div>
    <input type="text" id="message" />
    <input type="button" id="send" value="送信" disabled="disabled" />
    <ul id="list"></ul>
  </div>
  </form>
</body>
</html>

受信のみバージョンもテストしてみました。(送信と受信をわけることによって面白いことができそうです。)
WebForm2.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="aspEmptyWebSignalr.WebForm2" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
  <title></title>
  <script src="Scripts/jquery-1.6.4.min.js"></script>
  <script src="Scripts/jquery.signalR-1.1.2.min.js"></script>
  <script>
      $(function () {
          var connection = $.hubConnection("http://192.168.11.10/test/aspEmptyWebSignalr/signalr/hubs");
          var echo = connection.createHubProxy("echo");
          echo.on("Receive", function (text) {
              $("#list").append("<li>" + text + "</li>");
          });
          connection.start();
      })
  </script>
</head>
<body>
  <div>
    <ul id="list"></ul>
  </div>
</body>
</html>

IISにデプロイするときは$.hubConnectionの引数にURLをフルで書く必要があります。(デフォルトだと空)
デプロイは、IISマネージャでDefaultWebSiteの下にディレクトリを作成した後、VSのビルド->Webの発行で、発行方法「ファイルシストム」を選び、ターゲットに作成してディレクトリを指定します。
バケットキャプチャはWireSharkを使い、サーバ側(192.168.11.10)でキャプチャしました。クライアント(192.168.11.12)はFirefoxの最新バージョン(22)です。
captSignalR
送信したテスキトは、”aaaaaaaaaaaa”です。HTTPとはまた違うみたいですね。また調べていきたいです。ちなみにIE7/WindowsXPでも試しましたが、通信できませんでした。(WebSocketに対応していないブラウザだと違うプロトコルでやるのかなと思ったのですが・・まだ他に設定がいるのかも)あとiPhoneのSafariは動作確認しました。

ASP.NETの既存のサービスに追加する形で使うのに、とても便利だと思いました。

C#, Python で R.NET

最近の統計ブームにのって私もいろいろと興味があったので、「R」という統計ソフトを使ってみました。制御系の仕事をしていたときMatlabというシミュレーションソフトを使っていましたが、行列とかが簡単に扱えるインタープリタにとても驚かされました。とても魅力的なソフトなのですがとても高価なため個人では手軽に使えるものではありませんでした。Rのインタプリタを使っていると、そのときの感動がよみがえってきました。
調べてみるとRDotNet(http://rdotnet.codeplex.com/)を使うと、C#からRの機能が使えるということなので、いろいろとテストをしてみました。

環境: R 3.0.0, VisualStudio 2010/ Windows 7

using System;
using System.IO;
using System.Linq;
using RDotNet;
using System.Text;

class Program
{
    static void Main(string[] args)
    {
        var envPath = Environment.GetEnvironmentVariable("PATH");
        var rBinPath = @"C:\Program Files\R\R-3.0.0\bin\i386";
        Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + rBinPath);
        using (REngine engine = REngine.CreateInstance("RDotNet"))
        {
            engine.Initialize();

            StringBuilder command = new StringBuilder();
            commmand.Append(@"x <- 1:10;");
            commmand.Append(@"plot(x);");
            engine.Evaluate(commmand.ToString());
            Console.ReadLine();
        }
    }
}

まず、Rのコマンドラインで試した簡単なプロットをC#からやってみました。しかしこのやり方だと、単にリモート実行しているだけなのであまり意味がないと思い、以下のように修正しました。

class Program
{
    static void Main(string[] args)
    {
        var envPath = Environment.GetEnvironmentVariable("PATH");
        var rBinPath = @"C:\Program Files\R\R-3.0.0\bin\i386";
        Environment.SetEnvironmentVariable("PATH", envPath + Path.PathSeparator + rBinPath);
        using (REngine engine = REngine.CreateInstance("RDotNet"))
        {
            engine.Initialize();

            NumericVector nn = engine.CreateNumericVector(new double[] {1,2,3,4,5,6,7,8,9,10});
            engine.SetSymbol("nn", nn);
            engine.Evaluate("plot(nn)");

            Console.ReadLine();
        }
    }
}

こういったのは、スクリプト言語からの方が使い勝手がいいと思い、.NETでもあるのでIronPythonから呼び出してみようとトライしました。しかしモジュールをうまく読み込んでくれなかったので、普通のPythonに変更しました。しかしこれも、rpy2モジュールが64bitの環境でうまくインストールできなかったので、最終的にMacでテストしました。

sudo pip install rpy2

で簡単にインストールできました。

環境 : R 3.0.1, Python 2.7.1 / MacOSX 10.7.5

import rpy2.robjects as ro
import time

r = ro.r
q = r.seq(0,10);
r.plot(q);

time.sleep(3);

実行結果は以下のプロット画面です。この画面の実行はWindowsのRで行ったものです。

R

IronPythonでやる方法はまた調べたいと思います。

.NET Webフレームワーク Nancy をC#とF#で

.NET 用の軽量Webフレームワーク Nancy をC#とF#でテストしてみました。

以下記事参照
http://shiba-yan.hatenablog.jp/entry/20130509/1368107112「Sinatra ライクな .NET 用軽量 Web フレームワーク「Nancy」を使ってみた 」

SinatraはJRuby/GoogleAppEngineで遊んだことがありますが、とてもシンプルで気にいっていました。.NETフレームワークにもこのようなものが欲しいと思っていたので、この記事をみつけてすぐにいろいろと試そうと思ったのですが、F#でASP.NETを使って何かをつくろうとしていたので、後回しにしていました。しかしASP.NETとF#って、VS2012の環境でまだ環境が十分でないためか、なかなか思った形のものができませんでした。(セルフホストのものはいろいろあるのですが・・)
そのときタイミングよくNancyでF#を使える以下の記事も見つけたので、C#とF#両方あわせて動くものを作ってみました。

http://qiita.com/yohfee/items/1e5908cd720706805c94「F#でNancyをASP.NETでホストする 」

環境 : VisualStudio 2012 / Windows 8
プロジェクト : C# ASP.NET 空のWebアプリケーション に 追加Webフォーム
追加プロジェクト : F#ライブラリ
Library1.fs

namespace Library1
open Nancy
type FsTest() =
    inherit NancyModule()
    do
        base.Get.["/fs"] <- fun _ -> box "Hello Nancy F#"

Nugetで、Nancy追加

WebForm1.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace csAspEmptyWebFsNancy
{
    public class CsTest : Nancy.NancyModule
    {
        public CsTest()
        {
            Get["/cs"] = _ => "Hello Nancy C#";
        }
    }
}

NuGetでNancy,Nancy.Hosting.Aspnet追加

ブラウザで、/cs, /fs とアクセスするとそれぞれの文字列が表示されます。
F#でパラメータを渡すことを試したのですが、いろいろと難しくまたトライしてみたいと思います。(C#は記事にあります)
結構いろいろとテストしたのですが、結局これだけしか公開できないとは・・
まだまだです。

WindowsストアアプリでF#

最近のLINQネタの勢いで、F#に手をだしてしまいました。これまでLisp, Haskell, Clojure, Scalaなどなど関数型言語の勉強はしつつも、なかなか使う機会がないので、まったく身につきませんでした。本ばかりがたまる一方です。そして今度はF#。また同じ運命をたどるかも。
しかし今回は、Windowsストアアプリでも使えるということで、具体的な形になる可能性が高いという期待があります。(最近の流れからして動機としては十分です。)F#だけですべてを作るのではなく、C#から呼び出す形でデータ操作を専門にする使い方なら、かなり実用性があるのではと感じました。
オブジェクト指向言語は、WindowsなどのGUIの出現とともに必要とされ生まれ、そして関数型言語はインターネット時代、CPUマルチコア時代に必要とされ生まれてきたのでは、と思っています。最近の他の言語の傾向を見ていても、その必要性が今まで以上に感じられるようになってきました。
xamlListbox1
サンプルは、C#+XAMLのWindowsストアアプリから、正規表現の部分を記述したF#の関数を読んでいます。
結果は、ListBoxに書き出します。
正規表現の部分は、「実践F#関数型プログラミング入門」(技術評論社)を参考にしました。

環境 : VisualStudio 2012 / Windows 8

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace csfsStoreXaml02
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
        }
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
        private void Button_Click_3(object sender, RoutedEventArgs e)
        {
            var t = Module1.test3("ABC123-456,789");

            foreach (var v in t)
            {
                listBox1.Items.Add(v);
            }
        }
    }
}
module Module1
open System.Text.RegularExpressions

let re = Regex("[0-9]+")
let test3 x = 
    re.Matches(x) 
    |> Seq.cast<Match> 
    |> Seq.map(fun m -> m.Value) 
    |> Seq.toList

これが積極的に業務でも使えればいいのですが、まだ難しい状況が続くことと思います。それはあまり使われない言語を使うと保守性が悪くなるため、これを嫌う傾向は強いからです。これは十分理解できます。
最近Rubyですら使えないことがありました。データコンバートのツールを作るとき、開発時間でJavaの1/4くらい、コード量では約半分でしたが、Javaで作ることになりました。実際はプロトタイプはRubyでつくり、それをJavaに移植した後作りこみ、という形でやりましたが、基本仕様がすでに動いているということは、とても心強かったです。
F#もこのような使い方ができれば意義あることかもしれません。

ちなみに現在開発中のWindowsストアアプリとは、F#はまだまだということで、JavaScript+SVGのものと、C#+XAMLです。
しかし最近のMicrosoftの言語環境は、本当にマニアックすぎる!?

LINQ / VSTO

VSTOとは、Visual Studio Tools for Office の略です。前回WebのTableでやったLINQによるソートをExcelのシートでやってみました。ExcelのシートのプロクラムといえばVBAですが、前からC#でやってみたいと思っていて、だったらLINQだよね、となり、今ちょうど調査しているし、という流れでテストしてみました。

環境 VSTO / Visual Studio 2010 & Excel 2010 / Windows 7
プロジェクトは、Visual C# -> Office -> 2010 -> Excel 2010 ブック です。

using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using Microsoft.Office.Tools.Excel;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
using Excel = Microsoft.Office.Interop.Excel;
using Office = Microsoft.Office.Core;

namespace ExcelWorkbook
{
    public partial class Sheet1
    {
        private void InternalStartup()
        {
            this.button1.Click += new System.EventHandler(this.button1_Click);
        }
       private void button1_Click(object sender, EventArgs e)
        {
            DataTable table = new DataTable();
            Excel.Worksheet activeSheet = ((Excel.Worksheet)Application.ActiveSheet);

            table.Columns.Add("c1");
            table.Columns.Add("c2");
            table.Columns.Add("c3");
            for (int r = 1; r <= 6; r++)
            {
                table.Rows.Add(activeSheet.Cells[r, 1].Value, activeSheet.Cells[r, 2].Value, activeSheet.Cells[r, 3].Value);
            }
            var data = from dt in table.AsEnumerable()
                       orderby dt.Field<string>("c2")
                               select new
                               {
                                   a = dt.Field<string>("c1"),
                                   b = dt.Field<string>("c2"),
                                   c = dt.Field<string>("c3")
                               };
            int i=1;
            foreach (var d in data)
            {
                activeSheet.Cells[i, 1].Value = d.a;
                activeSheet.Cells[i, 2].Value = d.b;
                activeSheet.Cells[i, 3].Value = d.c;
                i++;
            }
        }
    }
}

table2

ボタンを押すと、中央の列がソートされます。

table3

VSTOって興味がありつつもなかなか使う機会が少ないのですが、やっばりまだVBAなのでしょうか。という私もVBAの手軽さはとても便利なので、よく使うのですが・・

LINQ and jQuery

最近LINQを使っていて、いろいろと調べていたところJavaScriptでの実装があることを知りました。

jQueryと「linq.js」を連携させてDOMをLINQにより処理するには?

http://www.atmarkit.co.jp/fdotnet/dotnettips/1059linqjquery/linqjquery.html

jQueryのオブジェクトに変換できるということなので、すごく興味がありテストしてみました。
jQueryは、メソッドチェーンで少ないコーディング量で複雑な処理が記述できることでとても好きなのですが、LINQもメソッドチェーンが使えることから、とても相性がいいと感じました。

環境:IE9 / Windows7

<html>
<head>
<script src="jquery-1.9.1.js" type="text/javascript"></script>
<script src="jquery.linq.js" type="text/javascript"></script>
<script type="text/javascript">

var dict;
var dt;

$(document).ready(function(){

	dict = $.Enumerable.Empty().ToDictionary();
	dict.Add("k1", [1001,"be","JKL"]);
	dict.Add("k2", [2, "abc","IIIII"]);
	dict.Add("k3", [300, "d1", "H"]);
	dict.Add("k4", [40, "col", "EFG"]);
	dict.Add("k5", [55, "f0000", "BCD"]);
	dict.Add("k6", [666, "eeee", "ABC"]);

	dataSet();
});
function dataSet(flg){
	var d = dict.ToEnumerable();
	
	if(flg > 0){
		flg --;
		d = d.OrderBy("$.Value["+flg+"]")
	}
	dt = d.Select(function (x) {
			return $("<tr/>").append($("<td/>").append(x.Value[0])).append($("<td/>").append(x.Value[1])).append($("<td/>").append(x.Value[2]))[0]
		})
		.TojQuery();
	
	dt.appendTo("#dt");

}
function btn(n){
	$('#dt tr').remove();
	dataSet(n);
}
</script>
</head>
<body>
<table border="1" id="dt"></table>
<input type="button" value="o1" onClick="btn(1)">
<input type="button" value="o2" onClick="btn(2)">
<input type="button" value="o3" onClick="btn(3)">
</body>
</html>

ボタンを押すとそれぞれのカラムのデータでソートして表示します。

table1

LINQの特徴の一つとして、DBのSQL文を文字列として分断して記述するのではなく、プログラム言語の一部として記述できる点があります。これもいいのですが、私はDBのSQL文がメモリのデータに対して使える点が便利に思っています。(LINQのクエリ式とSQL文はイコールではありませんが) SQL文と同じことをプログラム言語で書き換えようとすると、結構手間だったりするからです。

このlinq.jsライブラリは、jQueryとLINQとオブジェクトが相互変換可能なので、一つのメソッドチェーンで記述が可能です。これ、すごい!

サンプルは以前JavaScriptのフレームワークでこんな機能を使っていたと思いだし、作ってみました。JavaScriptでサーバからデータをJSONで取得してそれをブラウザで加工するということは、結構あります。そういった用途に使えそうです。ちなみに最新のJQuery 2.0.0では、IE9上で動作しませんでした。Firefox,ChromeはOKです。

ライブラリの中には詳しいリファレンスと実行テストができるファイルがあります。LINQの勉強するのにとてもいいかもしれませんね。

C# LINQのクエリ式

C#5.0の言語仕様で追加された、非同期処理を同期的に記述できるasync/awaitメソッドについても興味があるのですが、次々と新しい仕様を取り込むC#自体にとても興味があります。その中でもLINQはとても面白い深い存在なので、ちょっとまとめてみたいと思います。
環境: VisualStudio 2012 / Windows 8
プロジェクトは、C#コンソールアプリケーションです。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LinqTest
{
    class Program
    {
        static void Main(string[] args)
        {
            var q0 = Enumerable.
                Select(Enumerable.Where(Enumerable.Range(0, 10), p => p > 5), q => q * q);

            foreach (var v in q0)
            {
                Console.Write("q0:{0}\n", v);
            }

            var q1 = Extensions.MyAdd(Enumerable.
                Select(Enumerable.Where(Enumerable.Range(0, 10), p => p > 5), q => q * q), 2);

            foreach (var v in q1)
            {
                Console.Write("q1:{0}\n", v);
            }

            var q2 = Enumerable.
                Range(0, 10).Where(p => p > 5).Select(q => q * q);

            foreach (var v in q2)
            {
                Console.Write("q2:{0}\n", v);
            }

            var q3 = Enumerable.
                Range(0, 10).Where(p => p > 5).Select(q => q * q).MyAdd(2);

            foreach (var v in q3)
            {
                Console.Write("q3:{0}\n", v);
            }

            var q4 = from p in Enumerable.Range(0, 10) where p > 5 select p * p;

            foreach (var v in q4)
            {
                Console.Write("q4:{0}\n", v);
            }
            Console.Read();
        }
    }
    public static class Extensions
    {
        public static IEnumerable<int> MyAdd(
          this IEnumerable<int> x, int a)
        {
            foreach (int v in x)
            {
                yield return v + a;
            }
        }
    }
}

q0,q2,q4とq1,q3は、それぞれ同じ値を出力します。
36,49,64,81
38,51,66,83

クエリ式の3つのバリエーションのテストをしました。
1つ目が、スタティックメソッドの入れ子、2つ目がメソッドチェーン、3つ目がクエリ式です。
そして、スタティックメソッド、メソッドチェーンについては、MyAddという拡張メソッドを定義してそれを利用しています。(クエリ式でもやる方法はあるのかな? Rxを使う?)
言語仕様がどんどん変化している様子をまとめてみました。

オブジェクト指向言語の次の言語として注目されている関数型言語というものがありますが、新しいもの好きの私ももれなくHaskellとか勉強したことがありました。しかしどのように使うと便利なのか等、なかなかその概念が理解できませんでした。このLINQを触っていると、関数型言語の特徴の一つの遅延評価というものが、とてもよく理解できます。上の例でMyAddメソッドがまさにそれにあたります。このメソッド中のyield return という構文が、それを実現しているのですが、これは必要になったときに実行されます。必要になったときというのは、定義されたときではないということです。もともと関数というのは、宣言・定義・記述しただけでは実行されず、呼び出されたとき・使われたときに実行するので、関数型という言い方も腑に落ちるというわけです。
あと、冒頭に非同期処理のことを少し触れましたが、この非同期を記述するのにもLINQを使うことができるようです。ReactiveExtensions(以下Rx)と呼ばれるものですが、これはこれでとても興味深いので、また別の機会に掘り下げたいと思います。このRxの非同期処理のプログラムを見ていると、JavaScriptのjQuery.Deferredに似ています。もともとAjaxという非同期処理を有名にしたJavaScriptなので、これも腑に落ちるところですが、jQueryの非同期処理を連続して実行してもコードが見やすいしくみになっています。(メソッドチェーンという言い方も、私はjQueryのことをイメージして使っています。)
WindowsストアアプリのAPIがほとんど非同期になるということからも、このようなトレンドはどの言語も取り入れているということなのでしょう。
関数型言語にいきなりジャンプアップするのは難しいかもしれませんが、このようにLINQとかRxで徐々に体を慣らしていくと、いいのかもしませんね。オブジェクト指向もRubyで学習すると理解がしやすいという意見もあったりしますし、いろんな側面から技術を見るということは大切なことかもしれません。

Windows ランタイム C++ テンプレート ライブラリ (WRL)

C++/CXでもない、標準のC++からWinRTのAPIが使用できる方法が以下のサイトであったので、いろいろと調べてみました。
(C++/CLIからできないことはテスト済み)

WRL を使用して非同期操作を完了する
http://msdn.microsoft.com/ja-jp/library/vstudio/hh973451.aspx

エラー処理を省略するなどしてソースを見やすくしました。
環境 : VisualStudio 2012 / Windows 8

プロジェクトは、C++ の空のプロジェクトを使い、runtimeobject.libを「追加の依存ファイル」に追加します。


#include <Windows.Foundation.h>
#include <Windows.System.Threading.h>
#include <wrl/event.h>
#include <stdio.h>
#include <Objbase.h>

using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::System::Threading;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;

int main()
{
    // Initialize the Windows Runtime.
    RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);

    // Get the activation factory for the IThreadPoolTimer interface.
    ComPtr<IThreadPoolTimerStatics> timerFactory;
    HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory);

    // Create an event that is set after the timer callback completes. We later use this event to wait for the timer to complete. 
    // This event is for demonstration only in a console app. In most apps, you typically don't wait for async operations to complete.
    Event timerCompleted(CreateEventEx(NULL, NULL, CREATE_EVENT_MANUAL_RESET, WRITE_OWNER | EVENT_ALL_ACCESS));

    // Create a timer that prints a message after 2 seconds.

    TimeSpan delay;
    delay.Duration = 20000000; // 2 seconds.

    auto callback = Callback<ITimerElapsedHandler>([&timerCompleted](IThreadPoolTimer* timer) -> HRESULT
    {
        TimeSpan delay;
        HRESULT hr = timer->get_Delay(&delay);
        if (SUCCEEDED(hr))
        {
            printf("Timer duration: %2.2f seconds.\n", delay.Duration / 10000000.0);
        }
        // Set the completion event and return.
        SetEvent(timerCompleted.Get());
        return hr;
    });

    ComPtr<IThreadPoolTimer> timer;
    hr = timerFactory->CreateTimer(callback.Get(), delay, &timer);

    printf("Timer started...\n");

    // Wait for the timer to complete.
    WaitForSingleObjectEx(timerCompleted.Get(), INFINITE, FALSE);
    // All smart pointers and RAII objects go out of scope here.
}

cl.exe wrl-consume-asyncOp.cpp runtimeobject.lib

VisualStudioを使わなくても、コンパイルは上のように簡単にできますが、使うプロジェクトとか、ヘッダの中身を確認したかったので、あえて使ってみました。
(たしかに標準C++であるという確認のため)

実行すると以下のようにコンソールに出力します。

Timer started.
Timer duration: 2.00 seconds.

二秒後にコールバックを登録した処理を動作させるものです。WinRTのランタイムでなくてもできることですが、現在は標準C++からでもWinRTのAPIがコールできるという確認にとどめたいと思います。もっとWinRTらしい使い方を見つけたらまたテストしたいと思います。
あと、WRTが低レベル、C++/CXが高レベルという位置づけのようです。
ストアアプリがネイティブコードを出力しているということが少し実感できました。(よりハードに使いところで動作させることは、逆行する動きなのかそれともこれかのトレンドなのか・・)

C++/CLI + XAML

前々回のC++/CX + XAML に比較して、C++/CLIでもできるのかどうかテストしたところ、一応(形の上では?)できたので備忘録としておきたいと思います。
(WebViewもトライしてみましたができませんでした。方法はあるのかな?)

環境 : VisualStudio2012 / Windows 8
プロジェクトは、C++ CLRの空のプロジェクトを選びました。

using namespace System;
using namespace System::IO;
using namespace System::Windows;
using namespace System::Windows::Markup;
using namespace System::Windows::Navigation;
using namespace System::Threading; 

[STAThreadAttribute]
int main(array<System::String ^> ^args)
{
	FileStream^ fs = gcnew FileStream("xamltest.xaml", FileMode::Open, FileAccess::Read);
	Window^ win =  safe_cast<Window^>( XamlReader::Load(fs) );

	if(win != nullptr){
		win->Show();
	}
	Thread::Sleep(1000);

    return 0;
}

xamltest.xaml

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
	Title="XamlTest" Height="300" Width="500">
	<Grid>
		<Label VerticalAlignment="Center" HorizontalAlignment="Center">Xaml Test</Label>
	</Grid>
</Window>

実行すると、1秒間だけ以下の画面が表示されます。

xamtest

C++/CX WinRTコンポーネントとJavaScript

WinRTと呼ばれるWindowsストアアプリのランタイムライブラリが、Windows8の大きな特徴になります。これは、MS-DOS、Windows、.NETという変化に匹敵するものだと思います。
これまでの環境との互換性のしくみはなかなか複雑です。C++/CLIとC++/CXの違いについて誤解しやすいので、このあたり実際にプログラムを作りながら理解を深めているところです。
これら二つは共存できないもので、入れ替えるのもののようです。しかしコードはとてもよく似ています。C++/CLIの特徴であったマネージ領域のポインタの代替えのトラッキングハンドラ(キャレット文字(ハット記号)で表す)が使われます。
今回は、JavaScriptのストアアプリからC++/CX関数への値の受け渡しのテストをしました。C++/CXをランタイムコンポーネントとしてビルドして、これをストアアプリのプロジェクトから参照をします
前回も、JavaScriptからC++/CXを呼び出すことをしていますが、意味的にはかなり違っていると思います。
サンプルは、JavaScriptで配列をつくり、C++/CX側で合計を計算して引数の値と掛け合わせたあと、JavaScriptに値を戻しています。

環境 : VisualStudio2012 / Windows8

C++側
プロジェクトで、C++ -> ストアアプリ -> Windowsランタイムコンポーネントを選択します。

Class1.cpp

#include "pch.h"
#include "Class1.h"

using namespace cppStoreRunCompo02;
using namespace Platform;

Class1::Class1(){}

int Class1::arrSum(const Array<int>^ arr, int num)
{
    int sum = 0;
    for(int i = 0 ; i < arr->Length; i++)
    {
        sum += arr[i];
    }
    return sum * num;
}

JavaScript側
プロジェクトで、JavaScript -> ストアアプリ -> 空のアプリケーションを選択します。

default.js

(function () {
    "use strict";
    WinJS.Binding.optimizeBindingReferences = true;
    var app = WinJS.Application;
    var activation = Windows.ApplicationModel.Activation;
    app.onactivated = function (args) {
        if (args.detail.kind === activation.ActivationKind.launch) {
            if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
            } else {
            }
            args.setPromise(WinJS.UI.processAll());
        }
    };
    app.oncheckpoint = function (args) {
    };

    app.start();

    var cpp = new cppStoreRunCompo02.Class1();
    var arr = new Array(10);
    for (var i = 0; i < arr.length; i++) {
        arr[i] = i;
    }
    var sum = cpp.arrSum(arr, 2);
    alert("SUM : " + sum);
})();
function alert(str) {
    var md = new Windows.UI.Popups.MessageDialog(str);
    md.showAsync();
}

cppsum
WinRTは、C++/CXを使う以外にも、標準C++でWRT(Windows Runtime C++ Template Library)というものから使えるようです。試しにC++/CLIでWRTを使おうとしましたが、やはりだめでした。
これはCOMの改良版ということのようですが、.NETから進化しているものなのか、それともシンプル化したものなのか、そしてこの先どの方向に進んでいくのか、とても気になります。
このWinRTの存在は、今後のWindowsを占う上でも、とても重要なものとなりそうです。

C++/CX + XAML WebViewでストアアプリ

Windowsプラットホームの開発でいろいろと気になったことをテストしてきましたが、いよいよWindowsストアアプリの開発をしようということで、いろいろと準備を始めました。(本当はWindows Phone 8アプリの開発をやりたかったのですが、端末がないのでそれまではストアアプリでやれることはやっておこうと・・)
しかしこのストアアプリ、どんな言語で開発したらいいか、WindowsPhoneアプリへの移行がスムースのスタイルは、過去のライブラリを使う方法等、選択肢がいろいろとある分迷ってしまいます。JavaScript+HTML5かC#+XAMLか、と迷っていたらXAMLでWebViewを使う方法があると知ったので、テストしてみました。

環境: VisualStudio2012 / Windows8

新しいプロジェクトで、Visual C++ -> Windowsストア -> 新しいアプリケーション(XAML) を選びました。
(C#でもいいのですが、新しいC++/CXにも触れたかったので)

MainPage.xaml

<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <WebView x:Name="WebView1" ScriptNotify="wv_notify" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,88,0,0"/>
        <Button Content="Button" HorizontalAlignment="Left" Margin="40,28,0,0" VerticalAlignment="Top" Click="Button_Click_1"/>
        <TextBox x:Name="TextBox1" HorizontalAlignment="Left" Margin="166,28,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Height="38" Width="363" TextChanged="TextBox_TextChanged_1"/>
</Grid>

MainPage.xaml.cpp

void MainPage::OnNavigatedTo(NavigationEventArgs^ e)
{
	String^ html = "<html><head><script type='text/javascript'>\n" +
		"function jsFunc1(){ document.getElementById('test1').innerText = 'Hello!';}\n" +
		"function callCpp1(){ window.external.notify('js String');}\n" +
		"</script></head><body><h3>Test Program</h3><div id='test1'>Message area from C++ Program. Press button.</div>\n" +
		"<input type='button' value='btn1'  onClick='callCpp1()'>" +
		"</body></html>";

	WebView1->NavigateToString(html);
}
void cppxamlWebView1::MainPage::Button_Click_1(Platform::Object^ sender, Windows::UI::Xaml::RoutedEventArgs^ e)
{
	WebView1->InvokeScript("jsFunc1", nullptr);
}
void cppxamlWebView1::MainPage::wv_notify(Platform::Object^ sender, Windows::UI::Xaml::Controls::NotifyEventArgs e)
{
	TextBox1->Text = e.Value;
}

VisualStudioのデザイナーで作成すると、自動的にたくさんコードを生成するので、重要な部分のみ引用しました。(デフォルトのファイルからこれに関連する部分も修正する必要はあります)使用するXAMLコントロールは、ボタン、テキストボックス、WebViewの3つです。
ボタンを押すと、WebViewのJavaScript関数を呼び出し、divの内容を書き換えます。WebView内のボタンを押すと、JavaScriptがC++の関数を呼び出しテキストボックスを書き換えます。

起動時
webView1

変更後
webView2

偶然、最近のWebViewがらみの話題の延長みたいになってしまいました。

QtWebKit.QWebView を使ったPython、JavaScript連携

前々回、WebViewでのC#、JavaSCript間の連携の話題、そして前回IronPythonを使ったWebページの話題という流れて、どうしてもテストしておきたかったのが、Qtを使ったWebViewのPython、JavaScript間相互呼び出しです。
Qtは、LinuxZaurusの開発で経験がありますが(組み込みLinux用なのでQtopiaと呼ばれていましたが)、C++でクロスプラットフォームのGUIアプリケーションを開発できます。歴史は古いのですが、まだまだ現役のようです。最近また触れる機会があり、いろいろと調べてみたところ、WebKitを使ったプログラムが面白そうだということで、ちょっとはまっています。PySideというライブリを使って、Pythonからダイレクトに操作できる点も魅力です。
次の例は、起動するとPythonのプログラムからJavaScript関数を呼び出し、表示されたボタンをクリックすると、Python関数を呼び出すというものです。これはコンソールにメッセージを出力します。

環境: Python 2.7.3 + PySide 1.1.2 / Windows7


import sys
from PySide import QtWebKit,QtGui,QtCore

html = """
<html>
<script>
function pyMsg(str){
	pyObj.console(str);
}
function jsFunc(str){
	alert(str);
}
</script>
<body>
<input type="button" value="btn" onClick="pyMsg('js String')">
</body>
</html>
"""
 
class jsTest(QtCore.QObject):
	def __init__(self, parent=None):
		super(jsTest, self).__init__(parent)
	@QtCore.Slot(str)
	def console(self, msg):
		print msg

app = QtGui.QApplication(sys.argv)
view = QtWebKit.QWebView()
frame = view.page().mainFrame()
js = jsTest()
view.setHtml(html)
frame.addToJavaScriptWindowObject('pyObj', js)
frame.evaluateJavaScript("jsFunc('from py Function');")
view.show()
sys.exit(app.exec_())

他にも、クリックイベント等をフックできるので、デバッグやその他いろいろと楽しいことができます。
自分ブラウザみたいなものを作ってみたくなりますね。

SilverlightでIronPython or BrythonのPython / WebBrowser

(いまさらですが)SilverlightはFlashと同じように、ウェブブラウザにプラグインをインストールして、リッチコンテンツを動作させることができます。アニメーションやゲームなど、JavaScriptでは難しかったことができました。またFlashには、Flashムービ(コンテンツ)だけでなく、ActionScriptを使ったFlexというWebリッチクラアントの開発もできます。Silverlightも同様のことができます。後発なだけに、Flexでは既存HTMLと完全に分断してしまっているところを、HTMLとの親和性が高い設計になっています。どちらも個人的には、ウェブブラウザがリッチになるというよりも、インターネットクライアントアプリとしての自由度の高さがとても好みでした。しかし、最近はこれら(ブラウザプラグインによるリッチアプリ機能)がちょっと脇役にまわりつつある傾向にあります。
(ブラウザにプラグインを導入できないようにする傾向にある)
最初に顕在化したのは、iPhone,iPadによるFlashの排除したのが始まりでした。消費電力やセキュリティの問題が理由のようですが、PCだけでなくスマホ、タブレットを含めた未来を考えたとき、ある意味必然だったのかもしれません。
ブラウザ上で動かすリッチコンテンツには、ただリッチなだけでなく、マルチプラットホームで同じアプリケーションを走らせるという目的もあります。このマルチとは、Windows,Mac,Linuxというカテゴリーでかたられてきましたが、スマホ、タブレットといったものを含んで考えると、またちがったプラットホームを考える必要がでてくるのでしょう。
そこで最近勢いがあるのが、JavaScriptです。実行速度の向上により最近あらゆるものがJavaScriptで記述されるようになり、万能化しているようにさえ感じます。(Flashもコンバートできたり、ゲームエミュレータまでも)
CPUの違い、OSの違いがあっても、マルチプラットホームで動作するアプリケーションは、長年開発者がめざしてきたところです。
最近はJavaScript+HTML5という組み合わせが現実的に、その答えとなってきているようです。
Javaや.NETの中間レイヤーでマルチプラットホームを実現する方法も、中間言語レベルの互換性から記述言語レベルの互換性になったりするかもしれませんね。.NETのDLRはまた違った可能性を感じるのですが・・
と、いままでになく前置きが長くなりましたが、Silverlightのような環境が残って欲しいな、という思い(言語、実行環境に自由度が欲しいという観点)から、SilverlightによるIronPythonを使ったWebページと、JavaScriptの勢いを示す意味から、JavaScriptライブラリによるPythonを使ったWebページを同じプログラムでテストしてみました。
Silverlight

<html>
<head>
<script src="/dlr/dlr.js" type="text/javascript"></script>
</head>
<body>
<script type="text/python">
import System
import datetime

from System import TimeSpan
from System.Windows.Threading import *

def show_time(s,t):
    document.clock.innerHTML = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')  

timer1 = DispatcherTimer()
timer1.Interval = TimeSpan(0, 0, 1.0)
timer1.Tick += show_time
timer1.Start()

</script>
<span id="clock"></span>
</body>
</html>

JavaScript Library

<html>
<head>
<script src="brython.js"></script>
</head>
<body onLoad="brython()">
<script type="text/python">
import sys
import datetime
import time

def show_time():
    doc['clock'].text = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')    
show_time()
time.set_interval(show_time,1000)
</script>
<span id="clock"></span>
</body>
</html>

どちらも日時を表示するだけのプログラムです。インターバルタイマの記述に大きな違いがあります。
SilverlightでIronPythonを実行する環境には、Gestaltを使いました。

http://www.visitmix.com/labs/gestalt/

これは2009年11月から更新がありません。

Pythonが実行できるJavaScriptライブラリは、Brythonを使いました。

http://code.google.com/p/brython/

最新バージョンは、2013年3月ですから、まだピチピチですね。

Silverlightの方が起動に時間がかかります。どちらもFirefox18でテストしました。
比較した感想ですが、将来性はBrython、わくわく度はSilverlightといったところでしょうか。。

WebBrowser WindowsFormでJavaScriptからC#呼び出し

iPhoneやAndroidでは、WebViewを使って、ネイティブの機能をJavaScriptから使うことができたり、ネイティブコードからJavaScriptが実行できます。これと同じことをWindowsでもやってみました。(まだやってませんがWindows Phoneでも同様なのかな)
これは何かと便利で、Titanium Mobileのようにスマホアプリをハイブリッドで開発できるのも、このしくみを利用するからですね。

環境:VisualStudio 2010 / Windows 7

まず、以下のようにブラウザをC#で簡単につくれます。(フォームにツールボックスからWebBrowserをはりつけ)


namespace CSbrowser
{
    [System.Runtime.InteropServices.ComVisibleAttribute(true)]
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            webBrowser1.ObjectForScripting = this;
            webBrowser1.Navigate(new Uri("http://localhost/test.html"));
        }
        public void CSfunc1(string value)
        {
            MessageBox.Show(value);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            object[] args = { "arg1" };
            webBrowser1.Document.InvokeScript("JSfunc1", args);
        }
        private void button2_Click(object sender, EventArgs e)
        {
            string js = "alert('Click!')";
            webBrowser1.Url = new Uri("javascript:" + Uri.EscapeDataString(js) + ";");
        }
    }
}

次は、読み込むhtmlファイルです。(test.html)

<html>
<script>
var jsdata1 = 'jsdata1';
function JSfunc1(arg)
{
	alert('JSfunc1! : ' + arg);
}
function clk()
{
	window.external.CSfunc1(jsdata1);
}
</script>
<body>
<br><hr>
<center>
<h3><font color=blue>Test Page for C# WebBrowser.</font></h3>
<hr>
<input type='button' value='btn1' onClick='clk()'>
</center>
</body>
</html>

test.htmlをローカルのWebサーバで読み込めるようにして(XAMPPなど)、C#ソースをビルドしてたちあげると、

WebBrowserForm

このような画面になります。

中央の”btn1″ボタンをクリックすると、C#のCSfunc1()が呼ばれます。また、Windowsフォームの”button1″ボタンを押すと、JavaScriptのJSfunc1()が呼ばれ、”button2″ボタンを押すと、JavaScriptのalert()関数が実行されます。

まだいろいろと応用が考えられそうですね。

Office365をPowerShellで管理

Office365を使ってみて、このユーザの管理とかPowerShellでやってみたいと思い、試してみました。

前提条件はOffice365が使える状態になっていることです。以下のような画面で表示される、ユーザを表示したいと思います。
o365admin

まずコマンドレットをインストールする必要があります。以下のサイトから、サインインアシスタント、OnlineServicesモジュールをインストールしました。
環境 : Windows 8 Pro

http://onlinehelp.microsoft.com/office365-enterprises/hh124998.aspx

o365cmdinst

インストールが終了して、以下のコマンドで、多数のMSOnline用のコマンドレットが表示されればOKです。

Get-Command -module MSOnline

準備ができたら以下のコマンドを順に実行していきます。

Import-Module MSOnline
$Cred = Get-Credential
$Sess = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $Cred -Authentication Basic -AllowRedirection
Import-PSSession $Sess
Connect-MsolService –Credential $Cred

Get-MsolUser

出力結果

o365getuser

参考サイト

http://technet.microsoft.com/ja-jp/magazine/hh750396.aspx

IronPython で PowerShell

PowerShellは便利ですが、ちょっとしたプログラムを組もうとすると、やはりプログラム言語に分があります。そこでIronPythonからやってみました。Linuxで言えば、BashとPerlのような関係に近いかもしれません。(いやだいぶ違うかも・・こちらのがコマンドの移行がかなり簡単)

test.py

import powershell as ps

print ps.shell.get_command()	# gc

print ps.shell.get_childitem().sort("length")	# ls | sort -property length

print ps.shell.get_process("ipy")[0].ProcessName
# 'ipy'


http://ironpython.codeplex.com/releases/view/12482 にある IronPython-2.6-Samples.zip を利用しました。powershell.pyをtest.pyと同じフォルダにおいて、実行します。version2.6用のようですが、ipy 2.7.3でも動作しました。

環境 : Windows7 コマンドプロンプト

ipy test.py

Pythonでは、PowerShellコマンドのハイフンをアンダースコアに変更した名前になっています。パイプやプロパティ指定もできます。

Python使えるなぁ~

WindowsAzure Storage Python ライブラリ

WinowsAzure管理画面
az_storage

クラウドならではの特徴として、ストレージがあります。AzureではSQLも使えますが、クラウドらしさからいってAzure Table Storageというものを使ってみようと思います。
Azure Storageには、Blog Storage, Storage Queuesというのもありますが、Tableはキー/バリュー形式で一番汎用的と思うので、選択しました。

さて問題は実装の仕方ですが、サーバサイドでC#、Node.js、Pythonのどれでやろうか、と思いましたが、とりあえずストレージの部分だけテストしたかったので、Pythonでクライアントからアクセスする方法にしました。(サーバサイドだとストレージ以外の部分が面倒だつたので・・)

環境は、すでにPythonがインストールされているMac OS X Lionにしました。
まずは、Azureライブラリのインストール。

sudo eazy_install pip
sudo pip install azure

アカウント名、プライマリーキーは、Azureの管理画面からコピペ
create.py

from azure.storage import *
ts = TableService('アカウント名', 'プライマリキー')
ts.create_table('testTable')

insert.py

from azure.storage import *
ts = TableService('アカウント名', 'プライマリキー')
ts.insert_entity('testTable',{
    'PatitionKey':'key01',
    'RowKey':'1',
    'name':'xframe'
    })

get.py

from azure.storage import *
ts = TableService('アカウント名', 'プライマリキー')
entity = ts.get_entity('testTable', 'key01', '1')
print entity.name

以下の順でコマンド実行すると、

python create.py
python insert.py
python get.py

‘xframe’とコンソールに表示されます。
ここから発展させれば、ストレージについていろんなテストができそうです。

Node.js / WebMatrix を Azureで公開

var http = require('http');

http.createServer(function (req, res) {
   
    res.writeHead(200, { 'Content-Type': 'text/html' });
    res.end('Hello, world! Sample');

}).listen(process.env.PORT || 8080);

VisualStudioでなく、簡単にWebアプリケーションを開発、AzureにデプロイできるWebMatrixというツールがあるということを知りました。
上のようなNode.jsのソース(テンプレートのまま)をローカルで動作確認をして、すぐにAzureに公開ができます。
下のように「実行」(ローカル)「発行」(Azure)のボタンを押すだけ。(Azure以外も可能)

webmx4

Azure側は、管理画面から、Webサイトを作成します。
ここで発行プロファイルをダウンロードして、

webmx1

この発行プロファイルを、WebMatrix側で読み込みます。
これで、WebMatirxとAzureが紐付られます。

webmx2

あとは手順に従いデプロイします。

webmx3

Azureで設定したURLが表示されるので、これをクリックして表示確認できます。

とても簡単にできますし、他にも紹介されているサイトがたくさんありますが、Azureまわりに限らず、最近のMicrosoftの製品・サービスはバージョンアップによってよくインターフェイスや操作性が変わったりするので、この時点でできた記録をとっておく意味でも記事にしました。(実際にやってみると記憶にも残りますし、たぶんすぐ参考にならなくなるかもしれませんが、変更があったときにどこを基準に考えるか、ということが結構大切なときがあると思う今日このごろ・・)
それだけホットということですね。

次の課題は、Azureのストレージです。クラウドならではのストレージに興味があります。

Java Native Interface : C++/CLI

.NETフレームワークのC++/CLIの柔軟性を示す例として、一つの文字列を4つの方法でコンソール出力をしてみた。

#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <jni.h>
#include <iostream>

using namespace System;

void JavaPrint(char*);

int main(array<System::String ^> ^args)
{
	char str[100];

	sprintf(str, "Hello World\n");

	// .Net
	String^ s = gcnew String(str);
	Console::Write(s);

	// Win
	HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
	WriteConsole(hStdout, (CONST VOID *)str, (DWORD)strlen(str), NULL, NULL);

	// Std C
	printf("%s", str);

	// Java
	JavaPrint(str);

	std::cout << "Hit any key ..." << std::endl;
	getchar();
    return 0;
}

void JavaPrint(char *str)
{
	JNIEnv* env;
    JavaVM* jvm;
	JavaVMOption options[3];
	JavaVMInitArgs vm_args;

    options[0].optionString = "-Xmx128m";
    options[1].optionString = "-verbose:gc";
    options[2].optionString = "-Djava.class.path=C:/temp";

    vm_args.version = JNI_VERSION_1_6;
    vm_args.options = options;
    vm_args.nOptions = 3;

	JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
	
    jclass clazz = env->FindClass("JPrint");
	jmethodID mid = env->GetStaticMethodID(clazz, "SystemPrint", "(Ljava/lang/String;)V");
	env->CallStaticVoidMethod(clazz, mid, env->NewStringUTF(str));

    jvm->DestroyJavaVM();
}

これを実行すると以下のようになります。

Console4

Javaのコードはコンパイルして、C:\tempにclassファイルを配置しておきます。

public class JPrint{
	public static void SystemPrint(String arg){
		System.out.print(arg);
	}
}

なんか面白い。自己満足!(ネタ的にはちょっと古いけど、残しておきたかったので)
重要なのは、.NETにもJavaにも同時にアクセスできてしまうということです。
(こういうの過去資産の活用に使えるんですよね。)

最近C++/CXというものもでてきましたが、ネイティブとも.NETとも違うまた新しいスタイル(WinRT)の開発をすることができます。C++/CLIも陳腐化してしまうのかなぁ。
また勉強しないと・・

Facebook OAuth / ASP.NET

Facebookを使った認証をこれまでPHPで実装したことがありましたが、ASP.NET MVC4 Webアプリケーションのテンプレートを使うと、恐ろしいほど簡単にできてしまったので、そのメモです。

環境 : VisualStudio2012 / Windows 8

テンプレートをビルドすると、App_Start->AuthConfig.csの中には、以下のように、Twitter,Microsoftアカウントのものも用意されます。
今回FacebookのAppIDと、AppSecretを有効にしてコンパイルするだけです。

public static class AuthConfig
{
    public static void RegisterAuth()
    {
        //OAuthWebSecurity.RegisterMicrosoftClient(
        //    clientId: "",
        //    clientSecret: "");

        //OAuthWebSecurity.RegisterTwitterClient(
        //    consumerKey: "",
        //    consumerSecret: "");

        OAuthWebSecurity.RegisterFacebookClient(
            appId: "******************",
            appSecret: "*********");

        //OAuthWebSecurity.RegisterGoogleClient();
    }
}

これでデフォルト画面のログインボタンを押すと、Facebookのボタンがでてきます。

screenlogin

Facebookアプリ開発が初めての方は、開発者登録をしておく必要があります。

https://developers.facebook.com/apps

新規アプリの追加画面で、以下のように「Facebookでログインするウェブサイト」にURLを入れ保存します。

fb1

保存すると、「Changes saved.なお、変更が反映されるまでにseveral minutesかかる場合があります。」とルー語が表示されますので、これで完了です。
このURLは、開発マシンのlocalhostでもOKです。

Azure Cmdlet

WindowsAzureをPowerShellを使って、管理しようと試してみました。(Windows8でテスト)

gcm -module Azure

WindowsAzureをPowerShellで管理するときに使うコマンドレット一覧が表示されます。
コマンドを使う前に、以下のことをする必要があるようです。

Import-AzurePublishSettingsFile <ダウンロードした資格情報のファイル>
Set-AzureSubscription -SubscriptionName <サブスクリプション名>

作成したサービス内容でも出してみましょう。

Get-AzureService

PowerShellによるAzureの情報表示がかなり簡単にできてしまいました。
しかし、ネットや書籍などでいろいろと調べましたが、情報の時期によってコマンドの使い方も違ったりして、いろいろと混乱しました。最近Windows8の登場で新しくなって部分の情報がまだ不足している感じがあります。
これはAzure以外のことを調べていてもそう思いました。それだけホットということなのでしょう。

azure2

あと、Thumprintは、VisualStudioでクラウドに配置をすると、cert:\CurrentUser\Myに作成されるようです。

Windows Azure セットアップ

はじめてWindowsAzureをつかってみました。
これまで情報だけでは知っていて、なんかめんどくさそうだなぁと思っていましたが、実際にやってみるととても簡単なのがわかります。
作業した流れについて以下に書いてみたいと思います。

まずどんな構成のものをつくるかですが、Webのインターフェイスがあって、なんからの処理結果をストレージに記録でき、クラウドの特色を生かせるものということで、WebロールでAzureストレージサービスを使うことにしました。

1) Live ID アカウント作成
  live.jpサイトから登録
2) WindowsAzure サブスクリプション購入
Azureサイトで登録
3) クラウドサービス作成
Azureサイト管理者ページより
4) WindowsAzureサンプルアプリ作成
VisualStdudioでビルド と Azureエミュレータで動作確認
5) WindowsAzureサンプルアプリ発行
  資格情報をAzureサイトからダウンロードして、VisualStudioにインポート
  サンプルアプリデプロイ
6) クラウドサービスにアクセス
  Auzreサイト管理ページに記載の***.cloudapp.netのURLにブラウザでアクセス

エミュレータで動作確認しているとき、アプリ側だけみてみるとASP.NETとかわりないのですが、ServiceDeployementsの画面でコンソールで何やら表示しているのを見ると、クラウドっぽくて面白いです。

azure1

まだまだいろんな機能がありますが、今度はADFSを使ってみたいと思っています。

PowerShell

やっぱり最初はこのネタで。
登場したときから、注目していました。PowerShellは以下二つの理由で興味があります。

  1. Unixシェルの進化バージョン
  2. GUIのWindowsでなぜCUI

現在でも仕事でUnixのシェルスクリプトは多用しています。このGUIの時代に、まだまだテキスト編集や、出力結果を渡したりするのにとても便利です。cat, sed, awk, grep などなど必需品です。
しかし、これらテキストベースであるため、ちょっとしたプログラムミスで期待した出力にならなかったり、とても注意が必要です。たとえば、CSVファイルの編集などしたいとき、カンマ区切りを考慮して目的のデータを取り出したりするときなど、実際の処理の流れとは別に、一文字単位の変換など細かいところまでコーディングする必要がありました。
PowerShellでは、テキストベースではなく、オブジェクトベースでパイプラインを構築できるので、処理の流れに集中することができます。Unixのように各コマンドのシンタックスに違いがなく、どのコマンドも統一的に扱うことができます。
これらは後発の強みですので、当然といば当然ですが、GUIのWindowsでこのようなものが作られたというところに、CUIの必要性を証明していてとても興味深いです。(パイプという概念を導入したUnixは偉大ですね)

Get-ChildItem | where{$_.length -gt 1000} | 
  select  Name,Length | sort -Property length

このような感じで、ファイルリスト(dir)をサイズでソースすることが簡単にできます。(1000byte以上を対象。エイリアスも入っていて統一感がありませんが、SQL的に見えるのでこうしました。)
煩わしい文字列操作を意識せず、オブジェクトの操作ができるのは、直感的にデータ操作ができてとても便利です。
あと.Net APIとの親和性など、まだまだ魅力はあるのですが、勉強を進めながら使えるものを増やしていきたいと思っています。
はっきり言って、すごい好みです!