잊지 않겠습니다.

wrong javascript in jquery
<div id="mylinks">
    <a href="#" onclick="if(confirm('Follow the link?')) location.href='/someUrl1';">Link1</a>
    <a href="#" onclick="if(confirm('Follow the link?')) location.href='/someUrl2';">Link1</a>
</div>

good javascript in jquery
<div id="mylinks">
    <a href="/someUrl1">Link1</a>
    <a href="/someUrl2">Link2</a>
</div>

<script type="text/javascript">
    $("mylinks a").click(function() {
        return confirm('Floow the links?');
    });
</script>

Javascript를 사용할 때 '튀지 않는' Javascript를 만드는 방법
  * Javascript를 전혀 사용하지 않으면서 응용프로그램이나 기능을 구축해얒 한다. 실행 가능한 기능들을 채택하고 일반적인 HTML/CSS의 한계를 받아드린다.
  * 원 markup을 건드리지 않는 범의 한에서 Javascript를 사용한다. 그리고, 되도록 Javascript를 별도의 파일로 분리하자. 개별적으로 인식이 가능하고, 관리할 수 있는 방법을 제시해야지 된다.

Posted by Y2K
,
.NET으로 COM+ 객체를 만드는 예제.

.NET으로 COM+객체를 만들때는 먼저 Project Property에 Comvisible(true)로 설정이 되어 있어야지 된다. 그리고 assembly:Guid 속성에 component guid를 등록시켜야지만 com 객체를 만드는 가장 기초적인 설정이 끝이 난다. 이와같은 설정을 하면 작성된 dll이나 exe를 com+ 객체로 등록할 수 있다.

// Setting ComVisible to false makes the types in this assembly not visible 
// to COM components.  If you need to access a type in this assembly from 
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(true)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3308202e-a355-4c3b-805d-b527d1ef5fa3")]

그러나, dll을 등록한다고해서 library안의 class들이 모두 com객체로 사용할 수 있는 것이 아니다. dll은 여러개의 com객체를 담을 수 있는 상자이고, 그 상자안에 채워야지 될 com객체들은 각각 작성되어야지 된다. com을 이용하는 것은 com 객체 뿐 아니라, com 객체를 구성하고 있는 interface역시 사용할 수 있어야지 되기 때문에, com으로 외부에서 노출될 모든 interface와 class들은 Guid Class Property를 갖고, 각 Guid 값을 가져야지 된다.

com으로 사용되기 위해서, class와 interface가 가져야지 될 속성은 각각 다른데, interface는 ComInterfaceType Property와 Guid를 가져야지 되며, class는 Com으로 제공될 ComSourceInterfaces, ClassInterface, Transaction, Guid, Com 객체 사용에서 Pool과 CreateTimeOut을 제한하는 ObjectPooling attribute를 가져야지 된다.

com interface 구현 예제
#region Interfaces

[Description("ICSSimpleObject description")]
[Guid("2A59630E-4232-4582-AE47-706E2B648579")]
// The public interface describing the COM interface of the coclass 
public interface ICSSimpleObject
{
    #region Properties

    float FloatProperty { get; set; }

    #endregion

    #region Methods

    [Description("HelloWorld description")]
    string HelloWorld();

    void GetProcessThreadID(out uint processId, out uint threadId);

    [Description("DoTransaction description")]
    void DoTransaction();

    #endregion
}

[Guid("A06C000A-7A85-42dc-BA6D-BE736B6EB97A")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
// The public interface describing the events the coclass can sink
public interface ICSSimpleObjectEvents
{
    #region Events

    [DispId(1)]
    void FloatPropertyChanging(float NewValue, ref bool Cancel);

    #endregion
}
#endregion

com class 구현 예제
// The ObjectPooling attribute is used to configure the component's object 
// pooling. It can enable or disables object pooling and set the min. or  
// max. pool size and object creation timeout. 
[ObjectPooling(MinPoolSize=2, MaxPoolSize=10, CreationTimeout=20)]
// Creates the component with a new transaction, regardless of the state 
// of the current context.
[Transaction(TransactionOption.Required)]
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(ICSSimpleObjectEvents))]
[Guid("14EAD156-F55E-4d9b-A3C5-658D4BB56D30")]
public class CSSimpleObject : ServicedComponent, ICSSimpleObject
{
    #region Properties

    /// 
    /// The private members don't make it into the type-library and are 
    /// hidden from the COM clients.
    /// 
    private float fField = 0;

    /// 
    /// A public property with both get and set accessor methods.
    /// 
    public float FloatProperty
    {
        get { return this.fField; }
        set
        {
            bool cancel = false;
            // Raise the event FloatPropertyChanging
            if (null != FloatPropertyChanging)
                FloatPropertyChanging(value, ref cancel);
            if (!cancel)
                this.fField = value;
        }
    }

    #endregion

    #region Methods

    /// 
    /// A public method that returns a string "HelloWorld".
    /// 
    /// "HelloWorld"
    public string HelloWorld()
    {
        return "HelloWorld";
    }

    /// 
    /// A public method with two outputs: the current process Id and the
    /// current thread Id.
    /// 
    /// [out] The current process Id
    /// [out] The current thread Id
    public void GetProcessThreadID(out uint processId, out uint threadId)
    {
        processId = NativeMethod.GetCurrentProcessId();
        threadId = NativeMethod.GetCurrentThreadId();
    }

    public void DoTransaction()
    {
        try
        {
            // Operate on the resource managers like DBMS
            // ...
	
            ContextUtil.SetComplete();  // Commit
        }
        catch (Exception ex)
        {
            ContextUtil.SetAbort();     // Rollback
            throw ex;
        }
    }

    #endregion

    #region Events

    [ComVisible(false)]
    public delegate void FloatPropertyChangingEventHandler(float NewValue, ref bool Cancel);

    /// 
    /// A public event that is fired before new value is set to the
    /// FloatProperty property. The Cancel parameter allows the client 
    /// to cancel the change of FloatProperty.
    /// 
    public event FloatPropertyChangingEventHandler FloatPropertyChanging;

    #endregion
}
Posted by Y2K
,
Client 소스는 좀더 간단하다. Server의 경우에는 Bind와 Listen의 절차를 거치고, Listen에서 BeginListen, EndListen으로
AsyncCallback을 통해야지 되지만, Client의 경우에는 간단히 Connect만으로 가능하고, 하나의 Client에서는 역시 하나의
연결정도만 신경을 쓰면 되기 때문에 더욱더 편한 개발이 가능하다.

솔찍한 생각으로 예제 소스이긴 하지만, UI단만 조금 붙여버리면 거의 일반 프로그램들과 큰 차이가 안보인다.
Socket의 Close시에 Shutdown으로 Socket을 정리하는 부분에 신경을 쓰면 될 것 같다.


/****************************** Module Header ******************************\
* Module Name:	Program.cs
* Project:		CSSocketClient
* Copyright (c) Microsoft Corporation.
* 
* Sockets are an application programming interface(API) in an operating system
* used for in inter-process communication. Sockets constitute a mechanism for
* delivering incoming data packets to the appropriate application process or
* thread, based on a combination of local and remote IP addresses and port
* numbers. Each socket is mapped by the operational system to a communicating
* application process or thread.
*
*
* .NET supplies a Socket class which implements the Berkeley sockets interface.
* It provides a rich set of methods and properties for network communications. 
* Socket class allows you to perform both synchronous and asynchronous data
* transfer using any of the communication protocols listed in the ProtocolType
* enumeration. It supplies the following types of socket:
*
* Stream: Supports reliable, two-way, connection-based byte streams without 
* the duplication of data and without preservation of boundaries.
*
* Dgram:Supports datagrams, which are connectionless, unreliable messages of
* a fixed (typically small) maximum length. 
*
* Raw: Supports access to the underlying transport protocol.Using the 
* SocketTypeRaw, you can communicate using protocols like Internet Control 
* Message Protocol (Icmp) and Internet Group Management Protocol (Igmp). 
*
* Rdm: Supports connectionless, message-oriented, reliably delivered messages, 
* and preserves message boundaries in data. 
*
* Seqpacket:Provides connection-oriented and reliable two-way transfer of 
* ordered byte streams across a network.
*
* Unknown:Specifies an unknown Socket type.
* 
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
* 
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

#region Using directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Security;
using System.Security.Permissions;
#endregion


public class Program
{
    static void Main(string[] args)
    {
        // Receiving byte array 
        byte[] bytes = new byte[1024];
        try
        {
            // Create one SocketPermission for socket access restrictions
            SocketPermission permission = new SocketPermission(
                NetworkAccess.Connect,    // Connection permission
                TransportType.Tcp,        // Defines transport types
                "",                       // Gets the IP addresses
                SocketPermission.AllPorts // All ports
                );

            // Ensures the code to have permission to access a Socket
            permission.Demand();

            // Resolves a host name to an IPHostEntry instance           
            IPHostEntry ipHost = Dns.GetHostEntry("");

            // Gets first IP address associated with a localhost
            IPAddress ipAddr = ipHost.AddressList[0];

            // Creates a network endpoint
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 6000);

            // Create one Socket object to setup Tcp connection
            Socket sender = new Socket(
                ipAddr.AddressFamily,// Specifies the addressing scheme
                SocketType.Stream,   // The type of socket 
                ProtocolType.Tcp     // Specifies the protocols 
                );

            sender.NoDelay = true;   // Using the Nagle algorithm

            // Establishes a connection to a remote host
            sender.Connect(ipEndPoint);
            Console.WriteLine("Socket connected to {0}",
                sender.RemoteEndPoint.ToString());

            // Sending message
            // is the sign for end of data
            string theMessage = "Hello World!";
            byte[] msg = 
                Encoding.Unicode.GetBytes(theMessage +"");

            // Sends data to a connected Socket.
            int bytesSend = sender.Send(msg);

            // Receives data from a bound Socket.
            int bytesRec = sender.Receive(bytes);

            // Converts byte array to string
            theMessage = Encoding.Unicode.GetString(bytes, 0, bytesRec);

            // Continues to read the data till data isn't available
            while (sender.Available > 0)
            {
                bytesRec = sender.Receive(bytes);
                theMessage += Encoding.Unicode.GetString(bytes, 0, bytesRec);
            }
            Console.WriteLine("The server reply: {0}", theMessage);

            // Disables sends and receives on a Socket.
            sender.Shutdown(SocketShutdown.Both);

            //Closes the Socket connection and releases all resources
            sender.Close();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: {0}", ex.ToString());
        }
    }
}
Posted by Y2K
,
Socket을 사용해서 TCP/IP 서버를 만들게 되면 개발에서 가장 신경쓰게 되는 것이 Multi-Thread 문제이다.
이부분에 대해서 .NET에서 내놓은 최고의 Solution은 IAsyncCallback interface를 이용해서 BeginXXX 와
EndXXX를 이용하는 방법이다. 이 방법은 WebService client, Stream, Socket 등 데이터를 읽고, 쓰는데에
시간이 소요가 되어 Multi-Thread를 구현해야지 되는 거의 모든 경우에서 사용이 가능하다.

예제 소스는 다음과 같다. IPV6를 사용하는 소스를 IPV4로만 변경시킨 예제이다.


/****************************** Module Header ******************************\
* Module Name:	Program.cs
* Project:		CSSocketServer
* Copyright (c) Microsoft Corporation.
* 
* Sockets are an application programming interface(API) in an operating system
* used for in inter-process communication. Sockets constitute a mechanism for
* delivering incoming data packets to the appropriate application process or
* thread, based on a combination of local and remote IP addresses and port
* numbers. Each socket is mapped by the operational system to a communicating
* application process or thread.
*
*
* .NET supplies a Socket class which implements the Berkeley sockets interface.
* It provides a rich set of methods and properties for network communications. 
* Socket class allows you to perform both synchronous and asynchronous data
* transfer using any of the communication protocols listed in the ProtocolType
* enumeration. It supplies the following types of socket:
*
* Stream: Supports reliable, two-way, connection-based byte streams without 
* the duplication of data and without preservation of boundaries.
*
* Dgram:Supports datagrams, which are connectionless, unreliable messages of
* a fixed (typically small) maximum length. 
*
* Raw: Supports access to the underlying transport protocol.Using the 
* SocketTypeRaw, you can communicate using protocols like Internet Control 
* Message Protocol (Icmp) and Internet Group Management Protocol (Igmp). 
*
* Rdm: Supports connectionless, message-oriented, reliably delivered messages, 
* and preserves message boundaries in data. 
*
* Seqpacket:Provides connection-oriented and reliable two-way transfer of 
* ordered byte streams across a network.
*
* Unknown:Specifies an unknown Socket type.
* 
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
* 
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

#region Using Directive
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Security;
using System.Security.Permissions;
#endregion


public class Program
{
    static void Main(string[] args)
    {
        // Creates one SocketPermission object for access restrictions
        SocketPermission permission = new SocketPermission(
            NetworkAccess.Accept,     // Allowed to accept connections
            TransportType.Tcp,        // Defines transport types
            "",                       // The IP addresses of local host
            SocketPermission.AllPorts // Specifies all ports
            );

        // Listening Socket object
        Socket sListener = null;

        try
        {
            // Ensures the code to have permission to access a Socket
            permission.Demand();

            // Resolves a host name to an IPHostEntry instance
            IPHostEntry ipHost = Dns.GetHostEntry("");

            ///Get First IPV4 Address
            ///아직까지는 IPV4로 만들지 않으면 외부에서 접근을 못하는 경우가 많다.;
            IPAddress ipAddr = ipHost.AddressList.Where(a => a.AddressFamily != AddressFamily.InterNetworkV6).First();

            // Creates a network endpoint
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 6000);

            // Create one Socket object to listen the incoming connection
            sListener = new Socket(
                ipAddr.AddressFamily,
                SocketType.Stream,
                ProtocolType.Tcp
                );

            // Associates a Socket with a local endpoint
            sListener.Bind(ipEndPoint);

            // Places a Socket in a listening state and specifies the maximum
            // Length of the pending connections queue
            sListener.Listen(10);

            Console.WriteLine("Waiting for a connection on port {0}",
                ipEndPoint);

            // Begins an asynchronous operation to accept an attempt
            AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
            sListener.BeginAccept(aCallback, sListener);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: {0}", ex.ToString());
            return;
        }

        Console.WriteLine("Press the Enter key to exit ...");
        Console.ReadLine();
        
        if (sListener.Connected)
        {
            sListener.Shutdown(SocketShutdown.Receive);
            sListener.Close();
        }
    }


    /// 
    /// Asynchronously accepts an incoming connection attempt and creates
    /// a new Socket to handle remote host communication.
    ///      
    /// the status of an asynchronous operation
    ///  
    public static void AcceptCallback(IAsyncResult ar)
    {
        Socket listener = null;

        // A new Socket to handle remote host communication
        Socket handler = null;
        try
        {
            // Receiving byte array
            byte[] buffer = new byte[1024];
            // Get Listening Socket object
            listener = (Socket)ar.AsyncState;
            // Create a new socket
            handler = listener.EndAccept(ar);

            // Using the Nagle algorithm
            handler.NoDelay = true;

            // Creates one object array for passing data
            object[] obj = new object[2];
            obj[0] = buffer;
            obj[1] = handler;

            // Begins to asynchronously receive data
            handler.BeginReceive(
                buffer,        // An array of type Byt for received data
                0,             // The zero-based position in the buffer 
                buffer.Length, // The number of bytes to receive
                SocketFlags.None,// Specifies send and receive behaviors
                new AsyncCallback(ReceiveCallback),//An AsyncCallback delegate
                obj            // Specifies infomation for receive operation
                );

            // Begins an asynchronous operation to accept an attempt
            AsyncCallback aCallback = new AsyncCallback(AcceptCallback);
            listener.BeginAccept(aCallback, listener);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: {0}", ex.ToString());
        }
    }

    /// 
    /// Asynchronously receive data from a connected Socket.
    /// 
    /// 
    /// the status of an asynchronous operation
    ///  
    public static void ReceiveCallback(IAsyncResult ar)
    {
        try
        {
            // Fetch a user-defined object that contains information
            object[] obj = new object[2];
            obj = (object[])ar.AsyncState;

            // Received byte array
            byte[] buffer = (byte[])obj[0];

            // A Socket to handle remote host communication.
            Socket handler = (Socket)obj[1];

            // Received message
            string content = string.Empty;

            // The number of bytes received.
            int bytesRead = handler.EndReceive(ar);

            if (bytesRead > 0)
            {
                content += Encoding.Unicode.GetString(buffer, 0,
                    bytesRead);
                // If message contains "", finish receiving
                if (content.IndexOf("") > -1)
                {
                    // Convert byte array to string
                    string str =
                        content.TrimEnd(("").ToCharArray());
                    Console.WriteLine(
                        "Read {0} bytes from client.\n Data: {1}",
                        str.Length, str);

                    // Prepare the reply message
                    byte[] byteData =
                        Encoding.Unicode.GetBytes(str);

                    // Sends data asynchronously to a connected Socket
                    handler.BeginSend(byteData, 0, byteData.Length, 0,
                        new AsyncCallback(SendCallback), handler);
                }
                else
                {
                    // Continues to asynchronously receive data
                    byte[] buffernew = new byte[1024];
                    obj[0] = buffernew;
                    obj[1] = handler;
                    handler.BeginReceive(buffernew, 0, buffernew.Length,
                        SocketFlags.None,
                        new AsyncCallback(ReceiveCallback), obj);
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: {0}", ex.ToString());
        }
    }

    /// 
    /// Sends data asynchronously to a connected Socket.
    /// 
    /// 
    /// The status of an asynchronous operation
    ///  
    public static void SendCallback(IAsyncResult ar)
    {
        try
        {
            // A Socket which has sent the data to remote host
            Socket handler = (Socket)ar.AsyncState;

            // The number of bytes sent to the Socket
            int bytesSend = handler.EndSend(ar);
            Console.WriteLine(
                "Sent {0} bytes to Client",bytesSend);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: {0}", ex.ToString());
        }
    }
}
Posted by Y2K
,

0008. CSWindowsHook

Sample Codes 2010. 1. 5. 16:26
Windows Hooking의 경우에는 Windows message queue에 대한 이해가 좀 필요하다.
Windows는 Windows Message Queue를 통해서 각각의 Message를 전달하고, 그 Message에 따라 각기 다른 Action을 행한다.
WM_PAINT의 경우에는 화면을 그리라는 Message가 되고, WM_MOUSE의 경우에는 Mouse의 움직임에 따라 발생되는 Windows
Message이다.

Hooking은 이런 WIndows Message Queue에 Hook을 걸어서, 원래 처리되어야지 되는 함수가 아닌, 사용자 지정 Method에서
처리하게 하는 방법이다. 이것을 이용하면 Ctrl+Alt+Del의 기능도 막아버릴 수 있으며, 마우스를 움직여서 다른 동작을 하는 것도
막는 것이 가능하다. 또한 Mouse나 Keyboard의 모든 기록들을 저장할 수 있기 때문에 Windows에서 Cracking을 하는 경우에
왕왕 사용되는 방법이다.

먼저, WIN32 함수인 SetWindowsHookEx 함수를 DllImport시켜서 가지고 온다. 필요한 Native method의 선언은 다음과 같다.

internal delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

internal class NativeMethods
{
    /// 
    /// Hooking WIN32 API
    /// dwThreadId가 0인 경우에는 전역 hook
    /// 특정 handler안에서 Hooking을 하는 경우에는 Handle 값을 넣어준다.
    /// 
    /// 
    /// Hooking을 한 이후에 받을 method의 주소값 delegate된 method를 넣어줄수 있다.
    /// 
    /// 
    /// 
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SetWindowsHookEx(HookType hookType, HookProc callback, IntPtr hMod, uint dwThreadId);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern bool UnhookWindowsHookEx(IntPtr hhk);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
}

internal static class HookCodes
{
    public const int HC_ACTION = 0;
    public const int HC_GETNEXT = 1;
    public const int HC_SKIP = 2;
    public const int HC_NOREMOVE = 3;
    public const int HC_NOREM = HC_NOREMOVE;
    public const int HC_SYSMODALON = 4;
    public const int HC_SYSMODALOFF = 5;
}

internal enum HookType
{
    WH_KEYBOARD = 2,
    WH_MOUSE = 7,
    WH_KEYBOARD_LL = 13,
    WH_MOUSE_LL = 14
}

[StructLayout(LayoutKind.Sequential)]
internal class POINT
{
    public int x;
    public int y;
}

/// 
/// The MSLLHOOKSTRUCT structure contains information about a low-level keyboard 
/// input event. 
/// 
[StructLayout(LayoutKind.Sequential)]
internal struct MOUSEHOOKSTRUCT
{
    public POINT pt;        // The x and y coordinates in screen coordinates
    public int hwnd;        // Handle to the window that'll receive the mouse message
    public int wHitTestCode;
    public int dwExtraInfo;
}

/// 
/// The MOUSEHOOKSTRUCT structure contains information about a mouse event passed 
/// to a WH_MOUSE hook procedure, MouseProc. 
/// 
[StructLayout(LayoutKind.Sequential)]
internal struct MSLLHOOKSTRUCT
{
    public POINT pt;        // The x and y coordinates in screen coordinates. 
    public int mouseData;   // The mouse wheel and button info.
    public int flags;
    public int time;        // Specifies the time stamp for this message. 
    public IntPtr dwExtraInfo;
}

internal enum MouseMessage
{
    WM_MOUSEMOVE = 0x0200,
    WM_LBUTTONDOWN = 0x0201,
    WM_LBUTTONUP = 0x0202,
    WM_LBUTTONDBLCLK = 0x0203,
    WM_RBUTTONDOWN = 0x0204,
    WM_RBUTTONUP = 0x0205,
    WM_RBUTTONDBLCLK = 0x0206,
    WM_MBUTTONDOWN = 0x0207,
    WM_MBUTTONUP = 0x0208,
    WM_MBUTTONDBLCLK = 0x0209,

    WM_MOUSEWHEEL = 0x020A,
    WM_MOUSEHWHEEL = 0x020E,

    WM_NCMOUSEMOVE = 0x00A0,
    WM_NCLBUTTONDOWN = 0x00A1,
    WM_NCLBUTTONUP = 0x00A2,
    WM_NCLBUTTONDBLCLK = 0x00A3,
    WM_NCRBUTTONDOWN = 0x00A4,
    WM_NCRBUTTONUP = 0x00A5,
    WM_NCRBUTTONDBLCLK = 0x00A6,
    WM_NCMBUTTONDOWN = 0x00A7,
    WM_NCMBUTTONUP = 0x00A8,
    WM_NCMBUTTONDBLCLK = 0x00A9
}

/// 
/// The structure contains information about a low-level keyboard input event. 
/// 
[StructLayout(LayoutKind.Sequential)]
internal struct KBDLLHOOKSTRUCT
{
    public int vkCode;      // Specifies a virtual-key code
    public int scanCode;    // Specifies a hardware scan code for the key
    public int flags;
    public int time;        // Specifies the time stamp for this message
    public int dwExtraInfo;
}

internal enum KeyboardMessage
{
    WM_KEYDOWN = 0x0100,
    WM_KEYUP = 0x0101,
    WM_SYSKEYDOWN = 0x0104,
    WM_SYSKEYUP = 0x0105
}

여기에서 구성된 Hooking method들은 다음과 같다.

private bool SetGlobalLLMouseHook()
{
    // Create an instance of HookProc.
    globalLLMouseHookCallback = new HookProc(this.LowLevelMouseProc);

    hGlobalLLMouseHook = NativeMethods.SetWindowsHookEx(
        HookType.WH_MOUSE_LL,  // Must be LL for the global hook
        globalLLMouseHookCallback,
        // Get the handle of the current module
        Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]),
        // The hook procedure is associated with all existing threads running 
        // in the same desktop as the calling thread.
        0);
    return hGlobalLLMouseHook != IntPtr.Zero;
}

public int LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam)
{
    if(nCode >= 0)
    {
        // Marshal the MSLLHOOKSTRUCT data from the callback lParam
        MSLLHOOKSTRUCT mouseLLHookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT));

        // Get the mouse WM from the wParam parameter
        MouseMessage wmMouse = (MouseMessage)wParam;

        // Display the current mouse coordinates and the message
        String log = String.Format("X = {0} Y = {1}  ({2})\r\n", mouseLLHookStruct.pt.x, mouseLLHookStruct.pt.y, wmMouse);
        tbLog.AppendText(log);
    }

    // Pass the hook information to the next hook procedure in chain
    return NativeMethods.CallNextHookEx(hGlobalLLMouseHook, nCode, wParam, lParam);
}
Posted by Y2K
,
별다를 것이 없는 코드.
Visual Studio에서 Generate되는 code만을 간단히 이용하지만, Windows EventLog를 사용하는 법이 나온 부분만 체크해보면 될 것 같다.
또 하나가 있다면, ProjectInstaller 역시 살펴 볼 내용.

Windows Service를 등록하기 위해서는 InstallUtil을 이용해서 Service를 등록시켜야지 되는데 이때 등록할 ServiceName과 Service의
이름을 일치시켜주는 것이 필요하다.


private void InitializeComponent()
{
    ///서비스 등록 Account와 Password, UserName을 명시해준다.
    this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
    this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();
    // 
    // serviceProcessInstaller1
    // 
    this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalService;
    this.serviceProcessInstaller1.Password = null;
    this.serviceProcessInstaller1.Username = null;
    // 
    // serviceInstaller1
    // 
    ///서비스에 대한 내용을 기술한다. ServiceName의 경우에는 작성한 ServiceName과 반드시 일치해야지 된다.
    this.serviceInstaller1.Description = "All-In-One Code Framework Windows Service example";
    this.serviceInstaller1.DisplayName = "CSWindowsService Sample Service";
    this.serviceInstaller1.ServiceName = "CSWindowsService";
    // 
    // ProjectInstaller
    // 
    this.Installers.AddRange(new System.Configuration.Install.Installer[] {
                                this.serviceProcessInstaller1,
                                this.serviceInstaller1});
}

/// Required method for Designer support - do not modify 
/// the contents of this method with the code editor.
/// Windows EventLog에 대한 초기화를 행한다. 
private System.Diagnostics.EventLog eventLog1;
private void InitializeComponent()
{
    this.eventLog1 = new System.Diagnostics.EventLog();
    ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).BeginInit();
    // 
    // eventLog1
    // 
    this.eventLog1.Log = "Application";
    this.eventLog1.Source = "CSWindowsService";
    // 
    // MyService
    // 
    this.ServiceName = "CSWindowsService";
    ((System.ComponentModel.ISupportInitialize)(this.eventLog1)).EndInit();
}
Posted by Y2K
,
WPF를 이용한 Image animation

System.Windows.Media.Animation.StoryBoard controller를 이용해서 Image Animation을 할 수 있다.
Image Animation 형태는 StoryBoard Controller의 Property들을 변경시키면 가능하다.



int nextImageIndex;
List images = new List();

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // initialize the images collection
    images.Add(new BitmapImage(new Uri("Images/image1.jpg", UriKind.Relative)));
    images.Add(new BitmapImage(new Uri("Images/image2.jpg", UriKind.Relative)));
    images.Add(new BitmapImage(new Uri("Images/image3.jpg", UriKind.Relative)));
    images.Add(new BitmapImage(new Uri("Images/image4.jpg", UriKind.Relative)));

    nextImageIndex = 2;
}
       
private void VisbleToInvisible_Completed(object sender, EventArgs e)
{
    // change the source of the myImage1 to the next image to be shown 
    // and increase the nextImageIndex
    this.myImage1.Source = images[nextImageIndex++];

    // if the nextImageIndex exceeds the top bound of the ocllection, 
    // get it to 0 so as to show the first image next time
    if (nextImageIndex == images.Count)
    {
        nextImageIndex = 0;
    }

    // get the InvisibleToVisible storyboard and start it
    Storyboard sb = FindResource("InvisibleToVisible") as Storyboard;
    if(sb != null) 
        sb.Begin(this);

}

private void InvisibleToVisible_Completed(object sender, EventArgs e)
{
    // change the source of the myImage2 to the next image to be shown
    // and increase the nextImageIndex
    this.myImage2.Source = images[nextImageIndex++];

    // if the nextImageIndex exceeds the top bound of the ocllection, 
    // get it to 0 so as to show the first image next time
    if (nextImageIndex == images.Count)
    {
        nextImageIndex = 0;
    }

    // get the VisibleToInvisible storyboard and start it
    Storyboard sb = this.FindResource("VisibleToInvisible") as Storyboard;
    if(sb != null) 
        sb.Begin(this);
}   
Posted by Y2K
,
RSAServiceProvider를 이용해서 xml 파일에 서명 및 Decryption 하는 과정
RSAServiceProvider를 제공된 public key를 이용해서 얻어내는 것이 이 코드의 핵심.



private String publicOnlyKey;
private void btnSign_Click(object sender, EventArgs e)
{
    try
    {
        /////////////////////////////////////////////////////////////////
        // Create a new RSA signing key and export public key for 
        // verification.
        
        RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
        
        //Public Key exported
        //Public Key 뿐 아니라 Private Key도 얻어내는 것이 가능하다. 사용자에게 Key를 보내거나 저장할 때 이용 가능
        publicOnlyKey = rsaKey.ToXmlString(false);
        tbxRSAParameters.Text = publicOnlyKey;
        
        /////////////////////////////////////////////////////////////////
        // Sign the XML document.
        // 

        SignXml(xmlDoc, rsaKey);
        MessageBox.Show("XML file signed.");


        /////////////////////////////////////////////////////////////////
        // Save and display the signed document.
        // 

        xmlDoc.Save("test1.xml");
        tbxDigitalSignature.Text = xmlDoc.OuterXml;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}

///XML파일을 RSA를 이용해서 서명. SignedXml class가 있는 것을 기억하고 있을것!
public static void SignXml(XmlDocument Doc, RSA Key)
{
    // Check arguments.
    if (Doc == null)
        throw new ArgumentException("Doc");
    if (Key == null)
        throw new ArgumentException("Key");

    try
    {
        // Create a SignedXml object to generate signature.
        SignedXml signedXml = new SignedXml(Doc);

        // Add the key to the SignedXml document
        signedXml.SigningKey = Key;

        // Create a reference to be signed
        Reference reference = new Reference();
        reference.Uri = "";

        // Add an enveloped transformation to the reference
        XmlDsigEnvelopedSignatureTransform env = new XmlDsigEnvelopedSignatureTransform();
        reference.AddTransform(env);

        // Add the reference to the SignedXml object
        signedXml.AddReference(reference);

        // Compute the signature
        signedXml.ComputeSignature();

        // Get the XML representation of the signature and save
        // it to an XmlElement object.
        XmlElement xmlDigitalSignature = signedXml.GetXml();

        // Append the element to the XML document.
        Doc.DocumentElement.AppendChild(Doc.ImportNode(xmlDigitalSignature, true));
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

private void btnVerify_Click(object sender, EventArgs e)
{
    /////////////////////////////////////////////////////////////////////
    // Create a new RSA signing key and import public key for 
    // verification.
    //

    //NOTE:Public RSA Key를 이용해서 RSACryptoService Generate
    RSACryptoServiceProvider rsaKey = new RSACryptoServiceProvider();
    rsaKey.FromXmlString(publicOnlyKey);
    /////////////////////////////////////////////////////////////////////
    // Load the signed XML, and call VerifyXml to verify the signature of 
    // the signed XML.
    // 

    XmlDocument xmlDoc = new XmlDocument();
    xmlDoc.Load("test1.xml");

    bool result = VerifyXml(xmlDoc, rsaKey);

    if (result)
    {
        MessageBox.Show("The XML signature is valid.");
    }
    else
    {
        MessageBox.Show("The XML signature is not valid.");
    }
}

public static Boolean VerifyXml(XmlDocument Doc, RSA Key)
{
    // Check arguments.
    if (Doc == null)
        throw new ArgumentException("Doc");
    if (Key == null)
        throw new ArgumentException("Key");


    /////////////////////////////////////////////////////////////////////
    // Create a SignedXml object to verify the signature
    //

    SignedXml signedXml = new SignedXml(Doc);

    // Find Signature node and create a new XmlNodeList object
    XmlNodeList nodeList = Doc.GetElementsByTagName("Signature");

    // Throw an exception if no signature was found.
    if (nodeList.Count <= 0)
    {
        throw new CryptographicException(
            "Verification failed:" +
            " No Signature was found in the document.");
    }

    // This example only supports one signature for entire XML document
    if (nodeList.Count >= 2)
    {
        throw new CryptographicException(
            "Verification failed: More that one signature was found.");
    }

    // Load the first  node.  
    signedXml.LoadXml((XmlElement)nodeList[0]);

    // Check the signature and return the result.
    return signedXml.CheckSignature(Key);
}

private void btnChangeXML_Click(object sender, EventArgs e)
{
    // Modify the value of the Xml document for test. 

    XDocument xDoc = XDocument.Load("test1.xml");

    if (xDoc != null)
    {
        xDoc.Element("invoice").Element("items").
            Element("creditcard").Element("number").SetValue("19834210");

        xDoc.Save("test1.xml");

        tbxModifiedMessage.Text = xDoc.ToString();
    }
}
Posted by Y2K
,

0004. XmlGeneral

Sample Codes 2010. 1. 5. 13:21
xml파일을 각 ElementNode별로 읽고, XmlDocument를 생성하고 저장하는 sample code
XmlDocument에 새로운 Element를 생성하는 것은 생성후에 XmlDocument에 넣는 것이 아니라, XmlDocument를 통해 객체를
생성하고, 생성된 객체에 값을 넣은 이후에 XmlDocument에 Append하는 과정을 거쳐야지 된다는 것을 기억하면 매우 쉬운 소스다.


/****************************** Module Header ******************************\
* Module Name:	Program.cs
* Project:		CSXmlGeneral
* Copyright (c) Microsoft Corporation.
* 
* This C# sample project shows how to read a XML file by using XmlTextReader 
* or XmlNodeReader. It also shows, instead of using forward-only reader, how 
* to read, modify, and update Xml element using the XmlDocument class. This 
* class will load the whole document into memory for modification and we can 
* save the modified XML file to the file system.
* 
* The XML file used by the demo has this format:
* 
* 
*  
*    Gambardella, Matthew
*    XML Developer's Guide
*    Computer
*    44.95
*    2000-10-01
*    
*      An in-depth look at creating applications
*      with XML.
*    
*  
*  
*   ...
*  
* 
* 
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
* 
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

#region Using directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
#endregion


class Program
{
    static void Main(string[] args)
    {
        /////////////////////////////////////////////////////////////////////
        // Read XML document using the XmlTextReader class.
        // 

        // The XmlTextReader acts as a reader pointer that only moves forward.
        // Because it always moves forward and read a piece of data into 
        // memory buffer, it has better performance than the XmlDocument 
        // class which loads the whole document into memory.

        Console.WriteLine("Loading XML using XmlTextReader...");

        XmlTextReader xmlTextReader = new XmlTextReader(@"Books.xml");
        xmlTextReader.WhitespaceHandling = WhitespaceHandling.None;

        while (xmlTextReader.Read())
        {
            if (xmlTextReader.Name == "book")
            {
                Console.WriteLine(xmlTextReader.GetAttribute("id") + ": ");

                xmlTextReader.Read();
                string author = xmlTextReader.ReadElementContentAsString();
                string title = xmlTextReader.ReadElementContentAsString();
                string genre = xmlTextReader.ReadElementContentAsString();
                string price = xmlTextReader.ReadElementContentAsString();
                string publishDate = xmlTextReader.ReadElementContentAsString();
                string description = xmlTextReader.ReadElementContentAsString();

                Console.WriteLine(genre + " book \"" + title + "\" written by \"" +
                    author + "\", published on " + publishDate);
                Console.WriteLine(description);
            }
        }

        xmlTextReader.Close();


        /////////////////////////////////////////////////////////////////////
        // Read XML document using the XmlDocument and XmlNodeReader classes.
        // 

        // XmlNodeReader is similar to XmlTextReader but accepts an XmlNode 
        // instance as target to read. The following code shows how to use 
        // XmlDocument and XmlNodeReader to retrieve XML information. It is 
        // also a forward-only reader.

        Console.WriteLine("Loading XML using XmlDocument & XmlNodeReader...");

        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.Load(@"Books.xml");
        XmlNodeList xmlNodes = xmlDocument.GetElementsByTagName("book");
        foreach (XmlNode node in xmlNodes)
        {
            Console.WriteLine(node.Attributes["id"].Value + ":");

            XmlNodeReader xmlNodeReader = new XmlNodeReader(node);
            xmlNodeReader.Read();
            xmlNodeReader.Read();
            string author = xmlNodeReader.ReadElementContentAsString();
            string title = xmlNodeReader.ReadElementContentAsString();
            string genre = xmlNodeReader.ReadElementContentAsString();
            string price = xmlNodeReader.ReadElementContentAsString();
            string publishDate = xmlNodeReader.ReadElementContentAsString();
            string description = xmlNodeReader.ReadElementContentAsString();

            Console.WriteLine(genre + " book \"" + title + "\" written by \"" +
                author + "\", published on " + publishDate);
            Console.WriteLine(description);
        }


        /////////////////////////////////////////////////////////////////////
        // Make changes to the XmlDocument.
        // 

        // Modify a node value by first calling SelectSingleNode to navigate 
        // to that node and by setting its InnerText property to change its 
        // content.
        XmlNode nodeToModify = xmlDocument.DocumentElement.SelectSingleNode(
            "book/genre");
        nodeToModify.InnerText = "XML Tech";

        // Add a new XML node. In XML programming, we always call 
        // XMLDocument.Create*** to create an attribute or element. After 
        // that, we can add it into where we want by calling Node.AppendChild
        XmlElement newElement = xmlDocument.CreateElement("book");
        XmlAttribute newAttribute = xmlDocument.CreateAttribute("id");
        newAttribute.Value = "bk103";
        XmlElement authorElement = xmlDocument.CreateElement("author");
        authorElement.InnerText = "Mark Russinovich,David Solomon,Alex Ionecsu";
        XmlElement titleElement = xmlDocument.CreateElement("title");
        titleElement.InnerText = "Windows Internals, 5th edition";
        XmlElement genreElement = xmlDocument.CreateElement("genre");
        genreElement.InnerText = "Windows Server 2008";
        XmlElement priceElement = xmlDocument.CreateElement("price");
        priceElement.InnerText = "69.99";
        XmlElement publishDateElement = xmlDocument.CreateElement("publish_date");
        publishDateElement.InnerText = "2009-6-17";
        XmlElement descriptionElement = xmlDocument.CreateElement("description");
        descriptionElement.InnerText = "Windows Internals, 5th edition is the" +
            " update to Windows Internals, 4th edition to cover Windows Vista" +
            " and Windows Server 2008 (32-bit and 64-bit).";

        newElement.Attributes.Append(newAttribute);
        newElement.AppendChild(authorElement);
        newElement.AppendChild(titleElement);
        newElement.AppendChild(genreElement);
        newElement.AppendChild(priceElement);
        newElement.AppendChild(publishDateElement);
        newElement.AppendChild(descriptionElement);
        xmlDocument.DocumentElement.AppendChild(newElement);

        // Save the changes
        xmlDocument.Save("Modified Books.xml");

        // XmlLDocument does not have Close or Dispose method because it is 
        // an in-memory representation of an XML document. Once read, the 
        // file is no-longer needed.
    }
}



  
    Gambardella, Matthew
    XML Developer's Guide
    Computer
    44.95
    2000-10-01
    
      An in-depth look at creating applications
      with XML.
    
  
  
    Ralls, Kim
    Midnight Rain
    Fantasy
    5.95
    2000-12-16
    
      A former architect battles corporate zombies,
      an evil sorceress, and her own childhood to become queen
      of the world.
    
  

Posted by Y2K
,
.NET에서 Serialization은 객체를 저장하고, 객체를 다시 불러오는데 매우 유용하다. 그리고 네트워크로 Serialization된 객체를 전송하고,
다시 그 객체를 사용할 수 도 있는 .NET에서 핵심적인 기능중 하나이다.

XmlSerialization을 하기 위해 가장 유의할 점은 생성자는 input parameter가 없는 생성자만이 가능하다는 점을 항시 알아야지 된다.
input parameter가 있는 경우에는 Runtime시에 exception이 발생되게 된다.


/****************************** Module Header ******************************\
* Module Name:	Program.cs
* Project:		CSXmlSerialization
* Copyright (c) Microsoft Corporation.
* 
* This sample shows how to serialize an in-memory object to a local xml file 
* and how to deserialize the xml file back to an in-memory object using 
* C#. The designed MySerializableType includes int, string, generic, as well
* as customized type field and property.
* 
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
* All other rights reserved.
* 
* History:
* * 7/29/2009 3:00 PM Colbert Zhou Created
* * 8/20/2009 12:01 AM Jialiang Ge Reviewed
\***************************************************************************/

#region Using directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
using System.Collections;
#endregion


namespace CSXmlSerialization
{
    class Program
    {
        static void Main(string[] args)
        {
            /////////////////////////////////////////////////////////////////
            // Serialize the object to an XML file.
            // 

            // Create and initialize a MySerializableType instance.
            MySerializableType instance = new MySerializableType();
            instance.BoolValue = true;
            instance.IntValue = 1;
            instance.StringValue = "Test String";
            instance.ListValue.Add("List Item 1");
            instance.ListValue.Add("List Item 2");
            instance.ListValue.Add("List Item 3");
            instance.AnotherTypeValue = new AnotherType();
            instance.AnotherTypeValue.IntValue = 2;
            instance.AnotherTypeValue.StringValue = "Inner Test String";

            // Create the serializer
            XmlSerializer serializer = new XmlSerializer(typeof(MySerializableType));

            // Serialize the object to an XML file
            using (StreamWriter streamWriter = File.CreateText(
                "CSXmlSerialization.xml"))
            {
                serializer.Serialize(streamWriter, instance);
            }


            /////////////////////////////////////////////////////////////////
            // Deserialize from a XML file to an object instance.
            // 

            // Deserialize the object
            MySerializableType deserializedInstance;
            using (StreamReader streamReader = File.OpenText(
                "CSXmlSerialization.xml"))
            {
                deserializedInstance = serializer.Deserialize(streamReader) 
                    as MySerializableType;
            }

            // Dump the object
            Console.WriteLine("BoolValue: {0}", deserializedInstance.BoolValue);
            Console.WriteLine("IntValue: {0}", deserializedInstance.IntValue);
            Console.WriteLine("StringValue: {0}", deserializedInstance.StringValue);
            Console.WriteLine("AnotherTypeValue.IntValue: {0}", 
                deserializedInstance.AnotherTypeValue.IntValue);
            Console.WriteLine("AnotherTypeValue.StringValue: {0}", 
                deserializedInstance.AnotherTypeValue.StringValue);
            Console.WriteLine("ListValue: ");
            foreach (object obj in deserializedInstance.ListValue)
            {
                Console.WriteLine(obj.ToString());
            }
        }
    }


    /// 
    /// Serializable Type Declaration
    /// 
    [Serializable()]
    public class MySerializableType
    {
        // String field and property
        private string stringValue;
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }

        // Bool field and property
        private bool boolValue;
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        // Int field and property
        private int intValue;
        public int IntValue
        {
            get { return intValue; }
            set { intValue = value; }
        }

        // Another type field and property
        private AnotherType anotherTypeValue;
        public AnotherType AnotherTypeValue
        {
            get { return anotherTypeValue; }
            set { anotherTypeValue = value; }
        }

        // Generic type field and property
        private List listValue = new List();
        public List ListValue
        {
            get { return listValue; }
            set { listValue = value; }
        }

        // Ignore a field using NonSerialized attribute
        [NonSerialized()]
        private int ignoredField = 1;
    }

    /// 
    /// Another Type Declaration
    /// 
    [Serializable()]
    public class AnotherType
    {
        private string stringValue;
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }

        private int intValue;
        public int IntValue
        {
            get { return intValue; }
            set { intValue = value; }
        }
    }
}
Posted by Y2K
,