Archive for 5月, 2012

  1. Hello, COM(MSIL) World!

    Posted on 5月 22nd, 2012 by cx20

    MSIL

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は MSIL による COM クライアントの例となっている。

    ソースコード

     
    //  Microsoft (R) .NET Framework IL Disassembler.  Version 4.0.30319.1
    //  Copyright (c) Microsoft Corporation. All rights reserved.
     
     
    // Metadata version: v2.0.50727
    .assembly extern mscorlib
    {
      .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .zV.4..
      .ver 2:0:0:0
    }
    .assembly extern Shell32
    {
      .ver 1:0:0:0
    }
    .assembly Hello
    {
      .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 ) 
      .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                                 63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
      .hash algorithm 0x00008004
      .ver 0:0:0:0
    }
    .module Hello.exe
    // MVID: {558CDDD7-4AF4-48D6-A830-0DA2C5C15D19}
    .imagebase 0x00400000
    .file alignment 0x00000200
    .stackreserve 0x00100000
    .subsystem 0x0003       // WINDOWS_CUI
    .corflags 0x00000001    //  ILONLY
    // Image base: 0x01D10000
     
     
    // =============== CLASS MEMBERS DECLARATION ===================
     
    .class private auto ansi beforefieldinit Hello
           extends [mscorlib]System.Object
    {
      .method private hidebysig static void  Main(string[] args) cil managed
      {
        .entrypoint
        // コード サイズ       56 (0x38)
        .maxstack  5
        .locals init (class [Shell32]Shell32.Shell V_0,
                 class [Shell32]Shell32.Folder V_1,
                 object V_2,
                 bool V_3)
        IL_0000:  nop
        IL_0001:  newobj     instance void [Shell32]Shell32.ShellClass::.ctor()
        IL_0006:  stloc.0
        IL_0007:  ldc.i4.s   36
        IL_0009:  conv.i8
        IL_000a:  box        [mscorlib]System.Int64
        IL_000f:  stloc.2
        IL_0010:  ldloc.0
        IL_0011:  ldc.i4.0
        IL_0012:  ldstr      "Hello, COM(MSIL) World!"
        IL_0017:  ldc.i4.0
        IL_0018:  ldloc.2
        IL_0019:  callvirt   instance class [Shell32]Shell32.Folder [Shell32]Shell32.IShellDispatch5::BrowseForFolder(int32,
                                                                                                                      string,
                                                                                                                      int32,
                                                                                                                      object)
        IL_001e:  stloc.1
        IL_001f:  ldloc.1
        IL_0020:  ldnull
        IL_0021:  ceq
        IL_0023:  stloc.3
        IL_0024:  ldloc.3
        IL_0025:  brtrue.s   IL_0030
     
        IL_0027:  nop
        IL_0028:  ldloc.1
        IL_0029:  call       int32 [mscorlib]System.Runtime.InteropServices.Marshal::ReleaseComObject(object)
        IL_002e:  pop
        IL_002f:  nop
        IL_0030:  ldloc.0
        IL_0031:  call       int32 [mscorlib]System.Runtime.InteropServices.Marshal::ReleaseComObject(object)
        IL_0036:  pop
        IL_0037:  ret
      } // end of method Hello::Main
     
      .method public hidebysig specialname rtspecialname 
              instance void  .ctor() cil managed
      {
        // コード サイズ       7 (0x7)
        .maxstack  8
        IL_0000:  ldarg.0
        IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
        IL_0006:  ret
      } // end of method Hello::.ctor
     
    } // end of class Hello
     
     
    // =============================================================
     
    // *********** 逆アセンブルが完了しました ***********************
    // 警告: Win32 リソース ファイル Hello.res を作成しました。

    上記コードは、以下の C# の実行ファイルを ildadm.exe で逆アセンブルしたものである。

    ソースコード

    using System;
    using System.Runtime.InteropServices;
    using Shell32;
     
    class Hello
    {
        static void Main(string[] args)
        {
            Shell shell = new Shell();
            Folder folder;
            object vRootFolder = (long)ShellSpecialFolderConstants.ssfWINDOWS;
            folder = shell.BrowseForFolder(0, "Hello, COM(MSIL) World!", 0, vRootFolder);
            if (folder != null)
            {
                Marshal.ReleaseComObject(folder);
            }
            Marshal.ReleaseComObject(shell);
        }
    }

    コンパイル&実行方法(.NET Framework)

    C:¥> ilasm Hello.il
    C:¥> Hello

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(MSIL) Wolrd!                |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  2. Hello, COM(C++/CLI) World!

    Posted on 5月 21st, 2012 by cx20

    COM(C++/CLI)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は C++/CLI による COM クライアントの例となっている。

    ソースコード

    using namespace System;
    using namespace System::Runtime::InteropServices;
    using namespace Shell32;
     
    int main(array<System::String ^> ^args)
    {
        Shell^ shell = gcnew Shell;
        Folder^ folder;
        Object^ vRootFolder = (long)ShellSpecialFolderConstants::ssfWINDOWS;
        folder = shell->BrowseForFolder(0, "Hello, COM(C++/CLI) World!", 0, vRootFolder);
        if (folder != nullptr)
        {
            Marshal::ReleaseComObject(folder);
        }
        Marshal::ReleaseComObject(shell);
        return 0;
    }

    コンパイル方法

    C:¥> SET PATH=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin;%PATH%
    C:¥> tlbimp %SystemRoot%\system32\shell32.dll /out:Shell32.dll
    C:¥> cl /FU Shell32.dll Hello.cs /clr

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(C#) Wolrd!                  |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  3. Hello, COM(JScript.NET) World!

    Posted on 5月 20th, 2012 by cx20

    COM(JScript.NET)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は JScript.NET による COM クライアントの例となっている。

    ソースコード

    import System;
    import System.Runtime.InteropServices;
     
    var ssfWINDOWS = 36
     
    main();
     
    function main() {
        var shell = new ActiveXObject("Shell.Application");
        var folder = shell.BrowseForFolder( 0, "Hello, COM(JScript.NET) World!", 0, ssfWINDOWS );
        if ( folder != null )
        {
            Marshal.ReleaseComObject( folder );
        }
        Marshal.ReleaseComObject( shell );
    }

    コンパイル方法

    C:¥> jsc hello.js

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(JScript.NET) Wolrd!         |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  4. Hello, COM(F#) World!

    Posted on 5月 19th, 2012 by cx20

    COM(F#)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は F# による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。

    ソースコード(事前バインディング)

    open System
    open System.Runtime.InteropServices
    open Shell32
     
    let shell = new Shell32.ShellClass() 
    let vRootFolder = Shell32.ShellSpecialFolderConstants.ssfWINDOWS
    let folder = shell.BrowseForFolder( 0, "Hello, COM(F#) World!", 0, vRootFolder )
    if folder <> null then Marshal.ReleaseComObject( folder ) |> ignore
    Marshal.ReleaseComObject( shell ) |> ignore

    コンパイル方法(事前バインディング)

    C:¥> SET PATH=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin;%PATH%
    C:¥> tlbimp %SystemRoot%\system32\shell32.dll /out:Shell32.dll
    C:¥> fsc -r:Shell32.dll Hello.fs

    ソースコード(実行時バインディング)

    open System
    open System.Reflection
    open System.Runtime.InteropServices
     
    let objType = Type.GetTypeFromProgID("Shell.Application")
    let shell = Activator.CreateInstance(objType)
    let param = [| (0 :> Object); ("Hello, COM(F#) World!" :> Object); (0 :> Object); (36 :> Object) |]
    let folder = shell.GetType().InvokeMember("BrowseForFolder", BindingFlags.InvokeMethod, null, shell, param )
    if folder <> null then Marshal.ReleaseComObject( folder ) |> ignore
    Marshal.ReleaseComObject( shell ) |> ignore

    コンパイル方法(実行時バインディング)

    C:¥> fsc Hello.fs

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(F#) Wolrd!                  |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  5. Hello, COM(VB.NET) World!

    Posted on 5月 18th, 2012 by cx20

    COM(VB.NET)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は VB.NET による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。

    ソースコード(事前バインディング)

    Imports System
    Imports System.Runtime.InteropServices
    Imports Shell32
     
    Module Hello
        Sub Main()
            Dim shell As New Shell
            Dim folder As Folder
            Dim vRootFolder As Object = ShellSpecialFolderConstants.ssfWINDOWS
            folder = shell.BrowseForFolder(0, "Hello, COM(VB.NET) World!", 0, vRootFolder)
            If Not folder Is Nothing Then
                Marshal.ReleaseComObject(folder)
            End If
            Marshal.ReleaseComObject(shell)
        End Sub
    End Module

    コンパイル方法(事前バインディング)

    C:¥> SET PATH=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin;%PATH%
    C:¥> tlbimp %SystemRoot%\system32\shell32.dll /out:Shell32.dll
    C:¥> vbc /r:Shell32.dll Hello.vb

    ソースコード(実行時バインディング)

    Imports System
    Imports System.Runtime.InteropServices
     
    Module Hello
        Sub Main()
            Dim shell As Object
            Dim folder As Object
            shell = CreateObject("Shell.Application")
            folder = shell.BrowseForFolder(0, "Hello, COM(VB.NET) World!", 0, 36)
            If Not folder Is Nothing Then
                Marshal.ReleaseComObject(folder)
            End If
            Marshal.ReleaseComObject(shell)
        End Sub
    End Module

    コンパイル方法(実行時バインディング)

    C:¥> vbc Hello.vb

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(VB.NET) Wolrd!              |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  6. Hello, COM(C#) World!

    Posted on 5月 17th, 2012 by cx20

    COM(C#)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は C# による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。

    ソースコード(事前バインディング)

    using System;
    using System.Runtime.InteropServices;
    using Shell32;
     
    class Hello
    {
        static void Main(String[] args)
        {
            Shell shell = new Shell();
            Object vRootFolder = (long)ShellSpecialFolderConstants.ssfWINDOWS;
            Folder folder = shell.BrowseForFolder(0, "Hello, COM(C#) World!", 0, vRootFolder);
            if (folder != null)
            {
                Marshal.ReleaseComObject(folder);
            }
            Marshal.ReleaseComObject(shell);
        }
    }

    コンパイル方法(事前バインディング)

    C:¥> SET PATH=C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin;%PATH%
    C:¥> tlbimp %SystemRoot%\system32\shell32.dll /out:Shell32.dll
    C:¥> csc /r:Shell32.dll Hello.cs

    ソースコード(実行時バインディング)

    using System;
    using System.Reflection;
    using System.Runtime.InteropServices;
     
    class Hello
    {
        static void Main(String[] args)
        {
            Type objType = Type.GetTypeFromProgID("Shell.Application"); 
            Object shell = Activator.CreateInstance(objType);
            Object[] param = { 0, "Hello, COM(C#) World!", 0, 36 };
            Object folder = shell.GetType().InvokeMember( 
                "BrowseForFolder", BindingFlags.InvokeMethod, null, shell, param );
            if (folder != null)
            {
                Marshal.ReleaseComObject(folder);
            }
            Marshal.ReleaseComObject(shell);
        }
    }

    コンパイル方法(実行時バインディング)

    C:¥> csc Hello.cs

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(C#) Wolrd!                  |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  7. Hello, COM(PowerShell) World!

    Posted on 5月 16th, 2012 by cx20

    COM(PowerShell)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は PowerShell による COM クライアント(実行時バインディング)の例となっている。

    ソースコード

    $ssfWINDOWS = 36
     
    function Main() {
        $shell = new-object -comobject Shell.Application
        $folder = $shell.BrowseForFolder( 0, "Hello, COM(PowerShell) World!", 0, $ssfWINDOWS )
    }
     
    Main

    実行方法

    C:¥> PowerShell -File hello.ps1
    

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(PowerShell) Wolrd!          |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  8. Hello, COM(JScript) World!

    Posted on 5月 15th, 2012 by cx20

    COM(JScript)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は JScript による COM クライアント(実行時バインディング)の例となっている。

    ソースコード

    var ssfWINDOWS = 36
     
    main();
     
    function main() {
        var shell = new ActiveXObject("Shell.Application");
        var folder = shell.BrowseForFolder( 0, "Hello, COM(JScript) World!", 0, ssfWINDOWS );
    }

    VBScript であれば Nothing を代入した時点でメモリが解放されるが、JScript では null を代入してもメモリは解放されず(厳密には、Nothing 値と null 値は別物である)、ガベージコレクションが行われたタイミングで解放される。
    以下は、上記の違いを表にまとめたものである。

    JScript VBScript VarType VarType値 内容
    undefined Empty vbEmpty 0 Empty 値 (未初期化)
    null Null vbNull 1 Null 値 (無効な値)
    Nothing vbObject 9 オートメーション オブジェクト

    WSH をホストとする JScript の実行であれば、プロセス終了時にメモリ解放されるが、HTA や IE をホストとした場合、メモリが解放されず問題になることがある。
    この場合、CollectGarbage メソッドを呼び出すことで強制的にガベージ コレクションを行うことは可能であるが、このメソッドは非公開メソッド(ヘルプに記載されていない)であり、利用は推奨されていない。
    別の回避方法としては、Nothing でメモリが解放できる VBScript を使用することが推奨されている。

    実行方法

    C:¥> CScript hello.js

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(JScript) Wolrd!             |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  9. Hello, COM(VBScript) World!

    Posted on 5月 14th, 2012 by cx20

    COM(VBScript)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は VBScript による COM クライアント(実行時バインディング)の例となっている。

    ソースコード

    Option Explicit
     
    Const ssfWINDOWS = 36
     
    Call Main()
     
    Sub Main()
        Dim shell
        Set shell = CreateObject("Shell.Application")
        Dim folder
        Set folder = shell.BrowseForFolder( 0, "Hello, COM(VBScript) World!", 0, ssfWINDOWS )
        If ( Not folder Is Nothing ) Then
            Set folder = Nothing
        End If
        Set shell = Nothing
    End Sub

    実行方法

    C:¥> CScript hello.vbs

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(VBScript) Wolrd!            |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+
  10. Hello, COM(VBA) World!

    Posted on 5月 13th, 2012 by cx20

    COM(VBA)

    COM(Component Object Model)はマイクロソフトの提唱するプログラム部品の仕様である。
    COM を用いて開発された部品であれば言語を問わず利用することができる。
    以下は VBA による COM クライアント(事前バインディングならびに実行時バインディング)の例となっている。

    ソースコード(事前バインディング)

    Sub Main()
        Dim shell As New Shell32.shell
     
        Dim vRootFolder
        vRootFolder = Shell32.ShellSpecialFolderConstants.ssfWINDOWS
     
        Dim folder As Shell32.folder
        Set folder = shell.BrowseForFolder(0, "Hello, COM(VBA) World!", 0, vRootFolder)
     
        If Not folder Is Nothing Then
            Set folder = Nothing
        End If
        Set shell = Nothing
    End Sub

    事前バインディング(参照設定)の設定有無は、以下のコードで確認することが可能である。

    ソースコード(参照設定確認)

    Sub ShowReferences()
        Dim vbp
        Set vbp = ActiveWorkbook.VBProject
     
        Dim ref
        For Each ref In vbp.References
            If ref.BuiltIn = False Then
                Debug.Print "[" & ref.Name & "]"
                Debug.Print "GUID        : [" & ref.GUID & "]"
                Debug.Print "FullPath    : [" & ref.FullPath & "]"
                Debug.Print "Description : [" & ref.Description&; "]"
                Debug.Print ""
            End If
        Next
    End Sub

    実行結果(参照設定確認)

    [stdole]
    GUID        : [{00020430-0000-0000-C000-000000000046}]
    FullPath    : [C:\Windows\system32\stdole2.tlb]
    Description : [OLE Automation]
     
    [Office]
    GUID        : [{2DF8D04C-5BFA-101B-BDE5-00AA0044DE52}]
    FullPath    : [C:\Program Files\Common Files\Microsoft Shared\OFFICE14\MSO.DLL]
    Description : [Microsoft Office 14.0 Object Library]
     
    [Shell32]
    GUID        : [{50A7E9B0-70EF-11D1-B75A-00A0C90564FE}]
    FullPath    : [C:\Windows\system32\shell32.dll]
    Description : [Microsoft Shell Controls And Automation]

    ソースコード(実行時バインディング)

    Sub Main()
        Dim shell
        Set shell = CreateObject("Shell.Application")
     
        Dim vRootFolder
        vRootFolder = 36 ' ssfWINDOWS
     
        Dim folder
        Set folder = shell.BrowseForFolder(0, "Hello, COM(VBA) World!", 0, vRootFolder)
     
        If Not folder Is Nothing Then
            Set folder = Nothing
        End If
        Set shell = Nothing
    End Sub

    実行結果

    +----------------------------------------+
    |Browse For Folder                    [X]|
    +----------------------------------------+
    | Hello, COM(VBA) Wolrd!                 |
    |                                        |
    | +------------------------------------+ |
    | |[Windows]                           | |
    | | +[addins]                          | |
    | | +[AppCompat]                       | |
    | | +[AppPatch]                        | |
    | | +[assembly]                        | |
    | |     :                              | |
    | |     :                              | |
    | |     :                              | |
    | +------------------------------------+ |
    | [Make New Folder]    [  OK  ] [Cancel] |
    +----------------------------------------+