2010年4月27日火曜日

.Net(Mobile) 無線Lan(WiFi)のON/OFFを行うには

無線LanのON/OFFを行うにはSetDevicePowerというAPIを使用します。
このSetDevicePowerの第一引数に渡す値が端末により異なるので注意が必要です。

手元にある機種がSoftbankのX04HTとDocomoのX01Aだけなので、この2台で確認した結果です。

まず端末のレジストリ「HEKEY_LOCAL_MACHINE/System/CurrentControlSet/Control/Power/State」を確認します。
{98C5250D-C29A-4985-AE5F-AFE5367E5006}で始まるものが無線Lanになります。この値が1なら接続状態で0が切断状態です。

{98C5250D-C29A-4985-AE5F-AFE5367E5006}の後に続く¥以降の文字列が端末により異なります。
SoftbankのX04HTは{98C5250D-C29A-4985-AE5F-AFE5367E5006}¥TNETW12511
DocomoのX01Aは{98C5250D-C29A-4985-AE5F-AFE5367E5006}¥AR6K_SD1

この¥以降の文字列はレジストリ「HEKEY_LOCAL_MACHINE/Software/Drivers/WLAN」の「AdapterName」の値です。


以下のサンプルコードはSoftbankのX04HTとDocomoのX01Aで検証しましたが、他の端末で動作するかわかりません。
Imports System.Runtime.InteropServices

Public Class Form1

    Private Enum DevicePowerState
        Unspecified = -1
        D0 = 0 ' Full On: full power, full functionality  
        D1 ' Low Power On: fully functional at low power/performance  
        D2 'Standby: partially powered with automatic wake  
        D3 'Sleep: partially powered with device initiated wake  
        D4 'Off: unpowered  
    End Enum

     _
    Private Shared Function SetDevicePower(ByVal pvDevice As String, ByVal dwDeviceFlags As Int32, ByVal deviceState As DevicePowerState) As Int32
    End Function

     _
    Private Shared Function DevicePowerNotify(ByVal pvDevice As String, ByVal state As DevicePowerState, ByVal dwDeviceFlags As Int32) As Int32
    End Function

    Private Const POWER_NAME As Int32 = 1

    Private Const wifiGUID As String = "{98C5250D-C29A-4985-AE5F-AFE5367E5006}"


    'WirelessLan ON
    Private Sub Button10_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button10.Click
        SetWiFi(True)
    End Sub

    'WirelessLan OFF
    Private Sub Button9_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button9.Click
        SetWiFi(False)
    End Sub

    Private Sub SetWiFi(ByVal isEnabled As Boolean)
        'レジストリよりWiFiのドライバ名を取得する
        Dim regDrivers As RegistryKey = Registry.LocalMachine.CreateSubKey("Software\Drivers\WLAN")
        Dim driverNm As String = regDrivers.GetValue("AdapterName").ToString
        Dim guid As String = wifiGUID & "¥" & driverNm


        'D0でON、D4でOFF
        If (isEnabled) Then
            DevicePowerNotify(guid, DevicePowerState.D0, POWER_NAME)
            SetDevicePower(guid, POWER_NAME, DevicePowerState.D0)
        Else
            DevicePowerNotify(guid, DevicePowerState.D4, POWER_NAME)
            SetDevicePower(guid, POWER_NAME, DevicePowerState.D4)
        End If
    End Sub
End Class

.Net(Mobile) BlutoothのON/OFFを行うには

BlutoothのON/OFFを行うにはBthSetModeというAPIを使用します。

Imports System.Runtime.InteropServices

Public Class Form1
    Public Enum RadioMode
        RadioOff = 0            'Bluetooth OFF
        Connectable = 1         'Bluetooth ON(他のデバイスから検索不可)
        Discoverable = 2        'Bluetooth ON(他のデバイスから検索可)
    End Enum
    
     _
    Public Shared Function BthGetMode(ByRef dwMode As RadioMode) As Integer
    End Function
    
     _
    Public Shared Function BthSetMode(ByVal dwMode As RadioMode) As Integer
    End Function

    'Bluetooth ON
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        SetBluetooth(True)
    End Sub
    
    'Bluetooth OFF
    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        SetBluetooth(False)
    End Sub

    Private Sub SetBluetooth(ByVal isEnabled As Boolean)
        If (isEnabled) Then
            Dim mode As RadioMode = RadioMode.RadioOff
            Dim ret As Integer = BthGetMode(mode)
            If mode = RadioMode.RadioOff Then
                ret = BthSetMode(RadioMode.Discoverable)
                If ret = 0 Then
                    Do
                        System.Threading.Thread.Sleep(100)
                        ret = BthGetMode(mode)
                        If ret <> 0 OrElse mode <> RadioMode.RadioOff Then
                            Exit Do
                        End If
                    Loop
                End If
            End If
        Else
            Dim mode As RadioMode = RadioMode.Connectable
            Dim ret As Integer = BthGetMode(mode)
            If mode = RadioMode.Connectable Or mode = RadioMode.Discoverable Then
                ret = BthSetMode(RadioMode.RadioOff)
            End If
        End If
    End Sub
End Class

2010年4月21日水曜日

.Net(Mobile) NumericUpDownコントロールで値を選択状態にする。

CompactFrameworkではNumericUpDownコントロールのSelectAllプロパティがありません。
NumericUpDownコントロールで値を選択状態にするにはAPIを使用します。

Public Class FrmPrint

    Public Const SETSEL As Integer = &HB1
    <DllImport("coredll")> _
    Public Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    End Function

    'NumericUpDownコントロールにFocusされた時、値を選択状態にする。
    Private Sub NumericUpDown1_GotFocus(ByVal sender As Object, ByVal e As System.EventArgs) _
    HandlesNumericUpDown1.GotFocus
            '入力文字を全選択する
            Dim nud As NumericUpDown = DirectCast(sender, NumericUpDown)
            SendMessage(nud.Handle, SETSEL, 0, nud.Value.ToString.Length)
    End Sub
    
End Class

2010年4月16日金曜日

.NET プリンターのプロパティ画面を表示するには

.NET VistaではPageSetupDialogでプリンタ設定ボタンが表示されないで書いた
プリンターのプロパティ画面を表示する方法ですが、プリンタを変更するとプリンタドライバに依存するDEVMODE 構造体部分がメモリ確保されていないためエラーになることがあり
Marshal.AllocCoTaskMemを使った方法に訂正します。


Imports System.Runtime.InteropServices

Public Class Form1
    <DllImport("winspool.drv", CharSet:=CharSet.Auto, SetLastError:=True)> _
    Private Shared Function OpenPrinter( _
    <MarshalAs(UnmanagedType.LPTStr)> ByVal pPrinterName As String, ByRef hPrinter As IntPtr, ByVal pDefault As IntPtr) As Int32
    End Function

    <DllImport("winspool.drv", SetLastError:=True)> _
    Private Shared Function ClosePrinter(ByVal hPrinter As IntPtr) As Int32
    End Function

    <DllImport("winspool.drv", SetLastError:=True)> _
    Private Shared Function DocumentProperties ( _
        ByVal hwnd As IntPtr, _
        ByVal hPrinter As IntPtr, _
        <MarshalAs(UnmanagedType.LPTStr)> ByVal pDeviceName As String, _
        ByVal pDevModeOut As IntPtr, _
        ByVal pDevModeIn As IntPtr, _
        ByVal fMode As Int32) As Int32
    End Function

    Private Const DM_OUT_BUFFER As Short = 2
    Private Const DM_IN_PROMPT As Short = 4
    Private Const DM_IN_BUFFER As Short = 8

    <DllImport("kernel32", SetLastError:=True)> _
    Private Shared Function GlobalLock(ByVal hmem As IntPtr) As IntPtr
    End Function
    
    <DllImport("kernel32", SetLastError:=True)> _
    Private Shared Function GlobalFree(ByVal hmem As IntPtr) As Int32
    End Function
    
    <DllImport("kernel32", SetLastError:=True)> _
    Private Shared Function GlobalUnlock(ByVal hMem As IntPtr) As Int32
    End Function


    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim printer As New Printing.PrinterSettings
        Dim ret As Boolean = ShowPrinterProperty(Me.Handle, printer) 
    End Sub
        
    Private Function ShowPrinterProperty(ByVal hwnd As IntPtr, ByVal printer As Printing.PrinterSettings) As Boolean
        Dim ret As Int32

        'プリンタのハンドルを取得する
        Dim hPrinter As IntPtr = IntPtr.Zero
        ret = OpenPrinter(printer.PrinterName, hPrinter, IntPtr.Zero)
        If (ret = 0 OrElse hPrinter = IntPtr.Zero) Then
            Return False
        End If

        Try

            'プリンタのDEVMODE構造体のサイズを取得する
            Dim iDevModeSize As Integer = DocumentProperties(IntPtr.Zero, hPrinter, printer.PrinterName, IntPtr.Zero, IntPtr.Zero, 0)

            'Input用のDEVMODE構造体のハンドルを取得する
            Dim hDevModeIn As IntPtr = printer.GetHdevmode()
            Dim pDevModeIn As IntPtr = GlobalLock(hDevModeIn)

            'OutOut用のDEVMODE構造体のメモリを確保する
            Dim pDevModeOut As IntPtr = Marshal.AllocCoTaskMem(iDevModeSize)
            Try

                '設定画面を開く
                ret = DocumentProperties(hwnd, hPrinter, printer.PrinterName, pDevModeOut, pDevModeIn, DM_IN_PROMPT Or DM_IN_BUFFER Or DM_OUT_BUFFER)
                If (ret = 1) Then
                    printer.SetHdevmode(pDevModeOut)
                End If

                '
                Return True

            Finally
                GlobalUnlock(hDevModeIn)
                GlobalFree(hDevModeIn)
                Marshal.FreeCoTaskMem(pDevModeOut)
            End Try
        Finally
            ClosePrinter(hPrinter)
        End Try
    End Function
End Class

Java認定資格 SJC-P 310-055

Java認定資格 SJC-P 310-055 に合格しましたヽ(*´∀`)ノ

会社が受験料を払ってくれたのですが、「落ちた場合は自己負担で受かるまで受験すること」だったので
バカ高い試験だし結構勉強しましたw


今までJavaを使った仕事はしたことがありません。
数年前に一度だけJavaの仕事の話があって、ちょっと勉強したぐらいです。
結局その仕事も流れて、業務では未経験です。

試験勉強は以下の2冊の参考書を使いました。
Sunテキスト Sun Certified Programmer for Java 2 Platform 5.0 [Exam310-055] SKILL-UP TEXT (SKILL-UP TEXT―Sunテキスト) (単行本)
徹底攻略 Java2 プログラマ問題集 Platform5.0 対応 (ITプロ/ITエンジニアのための徹底攻略) (単行本(ソフトカバー))

試験は60問で35問以上(58%)で合格です。時間は180分。
内容は思っていたより難しくなく、上記の2冊を勉強したら合格点は取れると思います。
私は52問正解(86%)でした。

試験はセパレータで区切られた席に座って行うのですが
隣の人のキーボードやマウスの「カチッカチッ」という音や、椅子が「ギギー」となるので結構集中できません。

私の隣には二人のおじさんが試験を受けておられ、すごい勢いで「カチッカチッ」となるので
同じ試験を受けているわけではないけれど「お~すっげ~」と感心してしまいました。
あと隣の人の独り言も気になりますw
「ここがこうで・・・」とかブツブツいって試験が終わったら「よっしゃー」と言って帰られましたw
防音用にヘッドホンがあるのですが、あんまり役に立ちませんでした。

試験問題はパソコンで行うのですが、グレーの背景に読みにくいフォントです。
時間はたっぷりあるので、ゆっくり問題を解いても見直す時間はあります。
が、ドラッグドロップ問題は見直すと前回の選択がクリアされた状態で表示されますヽ(`Д´#)ノ
私は面倒だったのでドラッグドロップ問題は見直ししませんでした・・・
できればドラッグドロップ問題は1回目でしっかり選択しておくことをお勧めします。

あと1問だけメモ用紙がいるような問題がありました。
受け付けの方は説明してくれませんでしたが、試験前にもらえるプラケースのなかに
プラスチックの下敷きとマジックが入っていて、これをメモにするそうです。
試験終了後に教えてもらえました(´Д⊂ヽ
メモ用紙がないのでヘルプ画面を立ち上げて検索文字を入力するテキストボックスをメモにしてました・・・私。

一番の難関は試験時間が長いので、途中で「もういいやぁ」という気分に襲われます。
ここをグッとこらえて、試験時間いっぱい全部使ってやるという気持ちで耐えるのですが
今度は寒さに襲われ、トイレに行きたくなりますw
女性は膝かけなど用意された方が良いと思います♪

2010年4月3日土曜日

あいつぐ仕様変更・・・プログラマー殺すに刃物はいらぬ

今回の開発は納期が短いので仕様が30%程しか確定してない状態で開発が始まった。
嫌だなぁとは思ったけれど、仕事だし「やれ」と言われればやるしかない。
そんな大きなプロジェクトでもないから大丈夫かなと思った自分が甘かった(つд⊂)

ある程度の前提条件などを聞き出して、開発を始めた。
もちろんプログラムには変更が入る可能性も含めて幅を持たせたし
ざっくり作って、仕様が確定するまであまり作りこまないようにした。

とりあえずプロトタイプを提出し仕様を固めてもらう。
固まったところから作りこみを始める。

けれど仕様が固まったところなのに、仕様変更が入る。
前提条件を覆すような仕様変更も入る。
2度3度・・・5度、6度・・・。

何度作っても、仕様変更。仕様変更。仕様変更。
作っても作っても終わらない。
同じところばっかり作ってるような気がして、全体の終わりも見えない。

もうね、ソースコードの美しさとかどうでもよくなるね。
心が挫けて、心が折れて、鬱っぽくなる・・・
変に悲しくて、変に攻撃的で。うわぁ~自分ヤバイって感じ初めて経験しました。・゚・(ノД`)・゚・。

私はプログラムは美しく書きたいんです。
仕様変更で少しずつ崩れていくのは仕方ないにしても、新規に作成する時だけは美しくしておきたいんです。
この気持ちが相次ぐ仕様変更には耐えられない。
せめて前提条件だけは変えてくれるな( ゚д゚ )クワッ!!

プログラマー殺すに刃物はいらぬ、仕様を三回変えれば良い とはよく言ったもんだ。

前提条件を覆すような仕様変更を何度も言われたら、そのシステムはもうどうでもいいわ。
愛着ゼロ。モチベーションもゼロ。
そんなプログラマからよいシステムなんて作れませんよ?わかってる?道連れだよ?

仕様はもうちょっとよく考えてね!

2010年4月2日金曜日

.NET Windowsサービス

Windowsサービスは滅多に作らないので、いつも作り方を忘れてしまうのでメモ。

VisualStudio2008の場合
Windowsサービスプロジェクトを作成します。

サンプルコードとして、1分間隔でイベントログを出力するようにします。
自動で作成される「Service1.vb」にコードを書きます。
Public Class Service1

    Private _timer As Timers.Timer

    Protected Overrides Sub OnStart(ByVal args() As String)
        ' サービスを開始するコードをここに追加します。このメソッドによって、
        ' サービスが正しく実行されるようになります
        Me._timer = New Timers.Timer
        Me._timer.Interval = 1000 * 60
        AddHandler Me._timer.Elapsed, AddressOf Timer_Elapsed
        Me._timer.Start()
    End Sub

    Protected Overrides Sub OnStop()
        ' サービスを停止するのに必要な終了処理を実行するコードをここに追加します。
        Me._timer.EndInit()
        Me._timer.Dispose()
    End Sub

    Private Sub Timer_Elapsed(ByVal sender As Object, ByVal e As Timers.ElapsedEventArgs)
        EventLog.WriteEntry("Timer_Elapsed")
    End Sub

End Class

次にインストーラを作成します。
まず、「Service1.vb」のデザイナ上で右クリックし「インストーラの追加」をクリックします。

「ProjectInstaller.vb」が追加されます。
ServiceInstallerコントロールのServiceNameプロパティを変更します。(サービス一覧に表示される名前です)


ソリューションにセットアッププロジェクトを追加します。


ソリューションエクスプローラで追加したセットアッププロジェクトを右クリックし「追加」→「プロジェクト出力」を選択します。


「プロジェクトの出力グループの追加」ダイアログより「プライマリ出力」を選択します。


ソリューションエクスプローラで追加したセットアッププロジェクトを右クリックし「表示」→「カスタム動作」を選択します。


表示されたカスタム動作エディタの「カスタム動作」を右クリックし「カスタム動作の追加」を選択します。


表示される「プロジェクトから項目を選択」ダイアログで「アプリケーションフォルダ」を選択し「OK」をクリックします。

つづいて表示されるダイアログから「WindowsService1(アクティブ)のプライマリ出力」を選択し「OK」をクリックします。


カスタム動作エディタの「インストール」、「確定」、「ロールバック」、「アンインストール」のそれぞれにプライマリ出力が追加されます。


あとはセットアッププロジェクトをビルドしインストールを実行します。
インストールの途中でユーザー名とパスワードを求められるので、
ユーザ名にコンピュータ名¥ログインユーザ名
パスワードにログインパスワードを入力します。

インストールが終了したらサービスを起動します。
Vistaの場合
コントロールパネル→管理ツール→サービスを起動し、サービス一覧に表示される「TestService」を開始します。
コントロールパネル→管理ツール→「イベントビューアを起動し、一分間隔でイベントログが出力されていることを確認します。