WindowsにElixirをインストールする方法
chocolateyをインストールして、chocolateyでElixirをインストールする。
1.管理者モードで起動したコマンドプロンプトで次を実行する。
@powershell -NoProfile -ExecutionPolicy unrestricted -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%systemdrive%\chocolatey\bin2.コマンドプロンプトを閉じる。もう一度管理者モードでコマンドプロンプトを起動して次を実行する。
cinst elixir
Ruby 1.9.2 と Rails 3.2 で、rake test に色をつける。ついでに自動テストも。
仕事で使わないとほんと腰が重い。Ruby 1.9とRails3をやっと使ってみる。
Rails1や2のころはテストを書く作業が大変だった。とくにfixturesのメンテナンスが洒落にならない。最近はfixturesではなくモックを使うプラグインが出て来ているとかで、多少楽になっていればいいなと思う。
試しに作ったプロジェクトで rake test とテストを実行したら色がついてなくて素っ気なさすぎるので、まず成功は緑、失敗は赤で表示するよう設定。ついでにautotestも入れてみよう。
via. http://seanbehan.com/ruby/color-output-with-testunit-autotest-and-ruby-1-9/
RailsプロジェクトのGemfileを修正してテスト実行時に、"test-unit"、"minitest"、minitestで結果表示を書式化する"turn"、"autotest"、以上を使うよう設定。
group :development, :test do gem 'test-unit' gem 'minitest' gem 'turn' gem 'ZenTest' gem 'autotest-rails-pure' end
そんでbundleを実行して必要なGemをインストール。
$ bundle install
test/test_helper.rb に以下を追加。
require 'test/unit/ui/console/testrunner'
class Test::Unit::UI::Console::TestRunner
def guess_color_availability
true
end
end
テストを走らせてみる。
$ rake test
テスト結果が色付きで表示されれば成功。続いて自動テストを実行する。
$ bundle exec autotest
.NETのフォームで2段階の継承をしてからイベントを作成するとフォームデザイナーがエラーを吐く件
VB.NET2010で確認。
- Form1を作成し、ボタンを1つ配置。ModifiersをProtectedにして継承先でイベント作成を可能にする。そしてビルドを実行。
- Form1を継承してForm2を作成。ビルドを実行。
- Form2を継承してForm3を作成。ビルドを実行。
- Form3にてボタンのClickイベントを記述。ビルドを実行。画面を閉じる。
- Form3を開こうとすると「値を Null にすることはできません。パラメーター名: objectType 」と表示されフォームデザイナーが起動しない。(無視して続行すれば開く)
ただしビルドはできるし、実行も問題ない。でも設計画面が開けないのではなあ。
.NETってフォームの継承は事実上1段だけで、多段継承は危ないってことかしら。でも画面で多段継承できないと、なんのための継承なんだか、という噺になるような。
念のためフィードバックセンターに出しておこう。
.NETでいろいろなコントロールの読み出し専用制御を一括で行うパネルを作ってみる
.NETのUIコントロールについて、設計の一貫性のなさに煩悶した。特に「TextBox系にしかReadOnlyがない」には参った。
データの表示と編集を同じフォームで処理したいケースは普通によくあるのではないか。みんなどうしているの。
ということで
http://d.hatena.ne.jp/zecl/20090201/p1
を参考にさせてもらい、配置したコントロールについて読み出し専用制御をするパネル「ReadOnlyPanel」を作ってみた。TextBox系はReadOnlyプロパティで、それ以外はメッセージを補足して入力操作を禁止(ついでにWM_ENABLEも捕まえて淡色表示をあるていど防止)することで、文字入力した部分は表示のみのときでもコピーができるようにした。
以下ソースコード。
Imports System.Runtime.InteropServices
Imports System.Security
Imports System.Security.Permissions
Imports System.ComponentModel
''' <summary>
''' 配置したコントロールについて一括でReadOnly制御ができるパネル。
''' </summary>
''' <remarks></remarks>
Public Class ReadOnlyPanel
Inherits Panel
'本パネルのReadOnlyプロパティ値保持用
Private _readonly As Boolean = True
'本パネルで管理するコントロールと、メッセージ処理用リスナを保持する辞書
Private _control_list As New Dictionary(Of Control, ReadOnlyMessageListenr)
''' <summary>
''' 本パネルに配置したコントロールを読み出し専用にするかを設定/取得します。
''' </summary>
<DefaultValue(False)> _
Public Property [ReadOnly] As Boolean
Get
Return _readonly
End Get
Set(ByVal value As Boolean)
'値を保存
_readonly = value
'本パネルでReadOnly管理するコントロールのReadOnlyを処理
For Each ctrl_and_listener As KeyValuePair(Of Control, ReadOnlyMessageListenr) In _control_list
If TypeOf ctrl_and_listener.Key Is ReadOnlyPanel Then
'子がEditorPanelなら、そのReadOnlyで制御
DirectCast(ctrl_and_listener.Key, ReadOnlyPanel).ReadOnly = value
ElseIf TypeOf ctrl_and_listener.Key Is TextBoxBase Then
'TextBox系なら、ReadOnlyで制御
'まずFalseにして、
DirectCast(ctrl_and_listener.Key, TextBoxBase).ReadOnly = False
If value Then
'Trueなら背景色もあわせて制御
DirectCast(ctrl_and_listener.Key, TextBoxBase).ReadOnly = True
DirectCast(ctrl_and_listener.Key, TextBoxBase).BackColor = ctrl_and_listener.Value.BackColor
End If
End If
Next
End Set
End Property
''' <summary>
''' 任意のコントロールをコンテナとして扱うかを調べて返します。
''' </summary>
Private Function IsContainer(ByRef aControl As Control) As Boolean
If TypeOf aControl Is IContainerControl Then
Return True
ElseIf TypeOf aControl Is Panel Then
Return True
ElseIf TypeOf aControl Is GroupBox Then
Return True
Else
Return False
End If
End Function
''' <summary>
''' 本パネルにコントロールを追加したときに、ReadOnly制御を差し込む処理を追加します。
''' </summary>
Protected Overrides Sub OnControlAdded(ByVal e As ControlEventArgs)
MyBase.OnControlAdded(e)
If Not Me.DesignMode Then DoControlAddedHander(Me, e)
End Sub
'#-- 内部処理
Private Sub DoControlAddedHander(ByVal sender As Object, ByVal e As ControlEventArgs)
Dim hook As ReadOnlyMessageListenr = Nothing
If Not TypeOf e.Control Is ReadOnlyPanel Then
If TypeOf e.Control Is TabControl Then
AddHandler e.Control.ControlAdded, AddressOf DoControlAddedHander
AddHandler e.Control.ControlRemoved, AddressOf DoControlRemovedHander
ElseIf IsContainer(e.Control) Then
AddHandler e.Control.ControlAdded, AddressOf DoControlAddedHander
AddHandler e.Control.ControlRemoved, AddressOf DoControlRemovedHander
For Each ctrl In e.Control.Controls
DoControlAddedHander(e.Control, New ControlEventArgs(ctrl))
Next
End If
If Not (TypeOf e.Control Is ReadOnlyPanel Or TypeOf e.Control Is TabControl) Then
hook = New ReadOnlyMessageListenr(Me, e.Control)
End If
End If
_control_list.Add(e.Control, hook)
End Sub
''' <summary>
''' 本パネルからコントロールを削除したときに、ReadOnly制御を差し込む処理を削除します。
''' </summary>
Protected Overrides Sub OnControlRemoved(ByVal e As ControlEventArgs)
If Not Me.DesignMode Then DoControlRemovedHander(Me, e)
MyBase.OnControlRemoved(e)
End Sub
'#-- 内部処理
Private Sub DoControlRemovedHander(ByVal sender As Object, ByVal e As ControlEventArgs)
If Not TypeOf e.Control Is ReadOnlyPanel Then
If TypeOf e.Control Is TabControl Then
RemoveHandler e.Control.ControlAdded, AddressOf DoControlAddedHander
RemoveHandler e.Control.ControlRemoved, AddressOf DoControlRemovedHander
ElseIf IsContainer(e.Control) Then
RemoveHandler e.Control.ControlAdded, AddressOf DoControlAddedHander
RemoveHandler e.Control.ControlRemoved, AddressOf DoControlRemovedHander
For Each ctrl In e.Control.Controls
DoControlRemovedHander(e.Control, New ControlEventArgs(ctrl))
Next
End If
End If
_control_list.Remove(e.Control)
End Sub
#Region "ReadOnly制御用メッセージリスナクラス"
Protected Class ReadOnlyMessageListenr
Inherits NativeWindow
Public Const WM_ENABLE As UInteger = &HA
Public Const WM_SETFOCUS As UInteger = &H7
Public Const WM_KILLFOCUS As UInteger = &H8
Public Const WM_KEYDOWN As UInteger = &H100
Public Const WM_KEYUP As UInteger = &H101
Public Const WM_CHAR As UInteger = &H102
Public Const WM_CUT = &H300
Public Const WM_PASTE As UInteger = &H302
Public Enum WM_MOUSE As Integer
WM_MOUSEFIRST = &H200
WM_MOUSEMOVE = &H200
WM_LBUTTONDOWN = &H201
WM_LBUTTONUP = &H202
WM_LBUTTONDBLCLK = &H203
WM_RBUTTONDOWN = &H204
WM_RBUTTONUP = &H205
WM_RBUTTONDBLCLK = &H206
WM_MBUTTONDOWN = &H207
WM_MBUTTONUP = &H208
WM_MBUTTONDBLCLK = &H209
WM_MOUSEWHEEL = &H20A
End Enum
<StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)> _
Public Structure ComboBoxInfo
Public Size As Integer
Public RectItem As Rectangle
Public RectButton As Rectangle
Public ButtonState As Integer
Public ComboBoxHandle As IntPtr
Public EditBoxHandle As IntPtr
Public ListBoxHandle As IntPtr
End Structure
<SuppressUnmanagedCodeSecurity()> _
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Public Shared Function GetComboBoxInfo(ByVal comboBoxHandle As IntPtr, ByRef pComboBoxInfo As ComboBoxInfo) As Boolean
End Function
Private _editor_panel As ReadOnlyPanel
Private _control As New Control
Private _control_backcolor As Color
Private _is_textbox_base As Boolean
Private _is_tabcontrol As Boolean
''' <summary>
''' リッスン対象コントロールの初期背景色を保持します。
''' </summary>
Public ReadOnly Property BackColor As Color
Get
Return _control_backcolor
End Get
End Property
''' <summary>
''' コンストラクタ
''' </summary>
Public Sub New(ByRef aEditorPanel As ReadOnlyPanel, ByRef aControl As Control)
AddHandler aControl.HandleCreated, AddressOf Me.OnHandleCreated
AddHandler aControl.HandleDestroyed, AddressOf Me.OnHandleDestroyed
_editor_panel = aEditorPanel
_control = aControl
_control_backcolor = aControl.BackColor
_is_textbox_base = TypeOf _control Is TextBoxBase
_is_tabcontrol = TypeOf _control Is TabControl
End Sub
''' <summary>
''' ハンドル生成時のイベントハンドラ
''' </summary>
Private Sub OnHandleCreated(ByVal sender As Object, ByVal e As EventArgs)
If TypeOf sender Is ComboBox Then
Dim cbi As ComboBoxInfo
cbi.Size = Marshal.SizeOf(cbi)
If GetComboBoxInfo(sender.Handle, cbi) Then
AssignHandle(cbi.EditBoxHandle)
End If
Else
AssignHandle(CType(sender, Control).Handle)
End If
End Sub
''' <summary>
''' ハンドル破棄時のイベントハンドラ
''' </summary>
Private Sub OnHandleDestroyed(ByVal sender As Object, ByVal e As EventArgs)
ReleaseHandle()
End Sub
''' <summary>
''' メッセージ処理
''' </summary>
Protected Overrides Sub WndProc(ByRef m As Message)
'編集用パネルのReadOnlyがTrueのとき
If _editor_panel.ReadOnly Then
'淡色表示をさせないため、WM_ENABLEを処理しない
If m.Msg = WM_ENABLE And m.WParam = 0 Then
m.Result = 0
Exit Sub
End If
'TextBox系以外はReadOnlyプロパティ制御できないので、
'特定のメッセージを無視することでReadOnly相当状態を実現する。
If Not _is_textbox_base Then
Select Case (m.Msg)
Case WM_SETFOCUS, WM_KILLFOCUS
m.Result = 0
Exit Sub
Case WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_CUT, WM_PASTE
m.Result = 0
Exit Sub
Case WM_MOUSE.WM_MOUSEFIRST,
WM_MOUSE.WM_MOUSEMOVE,
WM_MOUSE.WM_MOUSEMOVE,
WM_MOUSE.WM_LBUTTONDOWN,
WM_MOUSE.WM_LBUTTONUP,
WM_MOUSE.WM_LBUTTONDBLCLK,
WM_MOUSE.WM_RBUTTONDOWN,
WM_MOUSE.WM_RBUTTONUP,
WM_MOUSE.WM_RBUTTONDBLCLK,
WM_MOUSE.WM_MBUTTONDOWN,
WM_MOUSE.WM_MBUTTONUP,
WM_MOUSE.WM_MBUTTONDBLCLK,
WM_MOUSE.WM_MOUSEWHEEL
m.Result = 0
Exit Sub
End Select
End If
End If
'通常のメッセージ処理を実行
MyBase.WndProc(m)
End Sub
End Class
#End Region
End Class
QuillとS2Dao.NETで、データベース接続文字列を動的に変更する
via. http://d.hatena.ne.jp/senbei3/20090410
app.configのquillセクションにはデータベース情報(
ASP.NETだとweb.configを暗号化すればよいらしいけれどWindowsフォームアプリケーションではそうもいかない。
というわけで、app.configのDB接続文字列にはユーザー名とパスワードは書かずにおいて、アプリ実行時に動的に差し込む方法。当然DBアクセス前に行う必要がある。例えばメインフォームのLoadイベントでやる場合。
メインフォームのメンバ変数に以下を追加。
Protected _dataSourceDict As SelectableDataSourceProxyWithDictionary
メインフォームのLoadイベントに以下を記述。
'DIでデータソース辞書を取得 QuillInjector.GetInstance.Inject(Me) 'app.configのquillセクションで定義したデータソースを取得 Dim ds As DataSourceImpl = _dataSourceDict.DataSourceCollection("sampleDb") 'データベース接続文字列にユーザー名とパスワードを追加 ds.ConnectionString &= ";user id=username;password=mypass"
これで実行時にユーザー名とパスワードを動的に設定できる。
S2Dao.NET -> OLEDB -> SQL Serverで、IDENTITY操作にハマったのでメモ
Quillでのお話。S2Containerでも同じかな。
app.configの
Provider=SQLOLEDB.1;Data Source=serverName;Initial Catalog=databaseName;User ID=userName;Password=userPassword;
と、Providerにバージョン番号を付けると、DB種類を認識できずにS2DaoがStandardDBとして扱ってしまう。
これは
Provider=SQLOLEDB;Data Source=serverName;Initial Catalog=databaseName;User ID=userName;Password=userPassword;
とプロバイダ識別名だけを記述すればOK。
DB種類が判別できない状態ではEntityのID属性が正しく働かない。
例えば、
<ID(IDType.IDENTITY)> _
Public Property Id() As Integer
Get
Return _id
End Get
Set
_id = value
End Set
End Property
と書いてIDを自動発番に任せる。
ところがStandatdDBは当然ID属性をサポートしておらず、ほんとは"select @@identity"が必要なところでnullを返す。結果、Insert後のID取得処理で例外が発生する。
これで2時間もハマって悔しい!