'2008/06'에 해당되는 글 9건

  1. 2008/06/25 C#을 통한 VSS 6.0 (Visual SourceSafe 6.0) Automation
  2. 2008/06/25 .NET 플랫폼과 Unmanaged COM 관련 자료.
  3. 2008/06/25 C#에서 unmanaged dll 호출하기?
  4. 2008/06/25 Visual SourceSafe Automaion.
  5. 2008/06/18 Jay Kim의 광우병 관련 영상~
  6. 2008/06/05 좀 더 나은 enum 사용법. (1)
  7. 2008/06/05 C++ Unit Test Framework. (1)
  8. 2008/06/05 엑스파일..
  9. 2008/06/04 CriticalSection Block (Synchronized block in C++) (1)
2008/06/25 18:45

C#을 통한 VSS 6.0 (Visual SourceSafe 6.0) Automation

Visual Studio 2008기준으로 작성 했습니다.

1) Visual Studio에서 C# Console Project를 선택한다.
2) 자신이 만약  VSS 6.0을 사용한다면, 위에서 포스팅한 방법으로 VSS Automation DLL 을 찾은 후 참조에 추가해 준다.
사용자 삽입 이미지

팝업 되는 다이얼 로그에서 해당 DLL 을 선택 해 줍니다.

사용자 삽입 이미지

3) 소스에서 해당 레퍼런스를 사용하도록 선언하고, 해당 메쏘드를 찾아 사용하면 끝~

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

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

            IVSSDatabase dbcon = new VSSDatabaseClass();
            dbcon.Open("\\\\myproject\\srcsafe.ini", "randy", "randy");
            VSSItem vssItem = dbcon.get_VSSItem("$/SrcRoot/GetSomething", false);

            String LocalPath = "C:\\Temp\\GetSomethingr";
            vssItem.Get(ref LocalPath, 1);
        }
    }
}

참 번외로 컴맨드 라인 알아본게 아까워서.. 몇 자 적어봅니다.
컴맨드 라인으로 소스를 내려받는 방법. 뭐 자세한건 도움말에 다 나와 있습니다 :-)
소스세이프 컴맨드라인 실행을 위한 환경 변수 설정.
set ssuser=randy
set ssdir=\\server\share\vss

작업디렉토리 설정.
"C:\Program Files\Microsoft Visual Studio\VSS\win32\ss.exe" WorkFold $/_MyProject/Project1 D:\Project\Project1
->디렉토리 이동.

"C:\Program Files\Microsoft Visual Studio\VSS\win32\ss.exe" Get -R $/_MyProject/Project1


Trackback 0 Comment 0
2008/06/25 17:19

.NET 플랫폼과 Unmanaged COM 관련 자료.

InterOP 마살링.
http://msdn.microsoft.com/ko-kr/library/04fy9ya1%28VS.80%29.aspx

고급 수준의 COM 상호 운용성.
http://msdn.microsoft.com/ko-kr/library/bd9cdfyx%28VS.80%29.aspx

<TODO>
나중에 핵심만 추려내자~

Trackback 0 Comment 0
2008/06/25 16:54

C#에서 unmanaged dll 호출하기?

원문 : http://msdn.microsoft.com/ko-kr/magazine/cc301501(en-us).aspx


From the August 2002 issue of MSDN MagazineMSDN Magazine
Call Unmanaged DLLs from C#, Killing Processes Cleanly
Paul DiLascia C++ Q&A Archive
Download the code for this article: CQA0208.exe (47 KB)
Q How do I call a DLL or Win32® API function from my C# code if the function has a string (char*) output parameter? I can pass a string for an input parameter, but how do I get the returned string? Also, how do I call functions that require a struct or a callback, like GetWindowsRect and EnumWindows? I'm trying to convert from C++ and MFC, and I can't cope!
E. Nguyen

A One of the major benefits of Microsoft® .NET is that it provides a language-independent development system. You can write classes in Visual Basic®, C++, C#—whatever—and use them in other languages; you can even derive from classes in a different language. But what happens when you want to call some old-school unmanaged DLL? You have to somehow translate .NET objects into the structs, char*'s, and function pointers C expects. In techno lingo, your parameters must be marshaled. Marshaling is a big topic, but luckily you don't have to know much to get the job done.
      To call a DLL function from C#, first you must provide a declaration, something programmers using Visual Basic have been doing for years. In C#, it's DllImport:
using System.Runtime.InteropServices; // DllImport
public class Win32 {
[DllImport("User32.Dll")]
public static extern void SetWindowText(int h, String s);
}
      In C#, you use DllImport to tell the compiler where the entry point lives and bundle your wrapper functions inside a class. You can give this class any name you like; I chose Win32. You can even put the class inside a namespace, like I did in Figure 1. To compile Win32API.cs, type:
csc /t:library /out:Win32API.dll Win32API.cs
Now you have a Win32API.dll you can use in any C# project.
using Win32API;
int hwnd = // get it...
String s = "I'm so cute."
Win32.SetWindowText(hwnd, s);
The compiler knows to find SetWindowText in user32.dll and automatically converts your string to LPTSTR (TCHAR*) before calling. Amazing! How does .NET perform this magic? Every C# type has a default marshaling type. For strings, it's LPTSTR. But what happens if you try this for GetWindowText, where the string is an out parameter, not an in parameter? It doesn't work because strings are immutable. Really. You may not have noticed, but whenever you do something to a string, a new string is created. To modify the one and only actual string, you have to use StringBuilder:
using System.Text; // for StringBuilder
public class Win32 {
[DllImport("user32.dll")]
public static extern int GetWindowText(int hwnd,
StringBuilder buf, int nMaxCount);
}
The default marshaling type for StringBuilder is also LPTSTR, but now GetWindowText can modify your actual string.
int hwnd = // get it...
StringBuilder cb = new StringBuilder(256);
Win32.GetWindowText(hwnd, sb, sb.Capacity);
      So the short answer to your first question is, use StringBuilder.
      All that seems super, but what happens if the default marshaling type isn't what you want? For example, suppose you want to call GetClassName? Windows® gurus know that unlike most API functions, GetClassName takes LPSTR (char*), even in Unicode builds. If you pass a string, the common language runtime (CLR) will convert it to TCHARs—oops! Never fear, you can use MarshalAs to override the default:
[DllImport("user32.dll")]
public static extern int GetClassName(int hwnd,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder buf,
int nMaxCount);
Now when you call GetClassName, .NET passes your string as an ANSI char, not a wide one. Whew!
      So much for strings. What about structs and callbacks? As you might guess, .NET has a way to handle them, too. Take a simple sample, GetWindowRect. This function stuffs a RECT with a window's screen coordinates:
// in C/C++
RECT rc;
HWND hwnd = FindWindow("foo",NULL);
::GetWindowRect(hwnd, &rc);
      How do you call GetWindowRect from C#? How do you pass the RECT? You do it as a C# struct, using another attribute, StructLayout.
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
public int left;
public int top;
public int right;
public int bottom;
}
Once you have your struct defined, you can implement the wrapper like so:
[DllImport("user32.dll")]
public static extern int
GetWindowRect(int hwnd, ref RECT rc);
It's important to use ref so the CLR will pass your RECT as a reference so the function can modify your object, not a nameless stack copy. With GetWindowRect defined, you can call it like so:
RECT rc = new RECT();
int hwnd = // get it ...
Win32.GetWindowRect(hwnd, ref rc);
Note that you must use the ref in the call as well as the declaration—picky! The default marshaling type for C# structs is—what else?—LPStruct, so there's no need for MarshalAs. But if you made RECT a class instead of a struct, you'd have to implement the wrapper like this:
// if RECT is a class, not struct
[DllImport("user32.dll")]
public static extern int
GetWindowRect(int hwnd,
[MarshalAs(UnmanagedType.LPStruct)] RECT rc);
      In C#, just like C++, there are lots of ways to do things. But System.Drawing already has a Rectangle struct for handling rectangles, so why reinvent the wheel?
[DllImport("user32.dll")]
public static extern int GetWindowRect(int hwnd, ref Rectangle rc);
The runtime already knows how to marshal a Rectangle as a Win32 RECT. Please note, however, that there's no need to call GetWindowRect (or Get/SetWindowText for that matter) in real code, since the Windows.Forms Control class has properties for this: Control.DisplayRectangle to get the window rectangle, and Control.Text to get or set the text.
Rectangle r = mywnd.DisplayRectangle;
mywnd.Text = "I'm so cute";
      You only need the API wrappers I've shown if for some reason you only have an HWND, not a Control-derived object.
      Strings, structs, Rectangles... what else? Oh yes, callbacks. How do you pass a callback from C# to unmanaged code? All you have to do is remember to say "delegate."
delegate bool EnumWindowsCB(int hwnd,     int lparam);
Once you've declared your delegate/callback type, the wrapper goes like this:
[DllImport("user32")]
public static extern int
EnumWindows(EnumWindowsCB cb, int lparam);
Since the delegate line merely declares a delegate type, you have to provide an actual delegate in your class
// in your class
public static bool MyEWP(int hwnd, int lparam) {
// do something
return true;
}
then pass it to the wrapper like so:
EnumWindowsCB cb = new EnumWindowsCB(MyEWP);
Win32.EnumWindows(cb, 0);
      Astute readers will notice I glossed over the problem of lparam. In C, if you give EnumWindows an LPARAM, Windows will notify your callback with it. Typically lparam is a pointer to some struct or class that contains context info that you need to do whatever it is you're doing. But remember, you can never say "pointer" in .NET! So what to do? In this case, you can declare your lparam as IntPtr and use a GCHandle to wrap it:
// lparam is IntPtr now
delegate bool EnumWindowsCB(int hwnd, IntPtr lparam);

// wrap object in GCHandle
MyClass obj = new MyClass();
GCHandle gch = GCHandle.Alloc(obj);
EnumWindowsCB cb = new EnumWindowsCB(MyEWP);
Win32.EnumWindows(cb, (IntPtr)gch);
gch.Free();
      Don't forget to call Free when you're finished! Sometimes in C# you actually get to free your own memory, just like in the old days. To access the lparam "pointer" inside your enumerator, use GCHandle.Target.
public static bool MyEWP(int hwnd, IntPtr param) {
GCHandle gch = (GCHandle)param;
MyClass c = (MyClass)gch.Target;
// ... use it
return true;
}
      Figure 2 shows a class I wrote that encapsulates EnumWindows in an array. Instead of fussing with delegates and callbacks, you can write the following:
WindowArray wins = new WindowArray();
foreach (int hwnd in wins) {
// do something
}
Pretty neat! Believe it or not, there's a method to all this madness. Everything makes sense once you get the hang of it. You can even use DllImport-style wrappers in managed C++. With .NET, you can move freely between managed and unmanaged worlds, as long as you do the proper translation. Most of the time you don't have to do anything; it just works. Occasionally, you need MarshalAs or a wrapper like GCHandle. For more on interop, read "Platform Invoke Tutorial" in the .NET documentation.
      Figure 3 shows a little program I wrote. ListWin lists the top-level windows with switches so you can display HWNDs, class names, titles, and/or window rectangles, using RECT or Rectangle. Figure 4 shows a sample run. I stripped some of the code to save space here; as always, you can grab the full source from the link at the top of this article.

Figure 4 ListWin Sample
Figure 4 ListWin Sample

Q I'm writing an app that backs up files to a network drive. My program works unless a user has Microsoft Outlook® open; then my program can't copy the mailbox file (mailbox.pst) because Outlook opens it with exclusive access. I want to be able to kill Outlook if it's running. How can I kill a process cleanly?
Jose Mercando

A A program called tskill.exe (see Figure 5) comes with newer versions of Windows and it does what you want.

Figure 5 tskill
Figure 5 tskill

For example
tskill outlook
kills the running instance of Outlook. But if you want to write the code yourself, the safest way to kill a process is to post a WM_CLOSE message to its main window:
HWND hwnd = // get main window
PostMessage(hwnd, WM_CLOSE, 0, 0);
Once the message is posted, you usually should wait for the process to actually terminate:
HANDLE hp = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE,FALSE,pid);
WaitForSingleObject(hp, 5000); // wait up to 5 seconds
When the process terminates, it flips to the signaled state and WaitForSingleObject returns WAIT_OBJECT_0. If it returns something else, the process is either hung or still doing something. In that case, the only way to kill the process is to pull out the big bazooka, TerminateProcess.
if (WaitForSingleObject(hp, 5000) != WAIT_OBJECT_0)
TerminateProcess(hp,0); // Hasta la vista, baby!
      If you want to be really nice, you can send the main window a WM_QUERYENDSESSION before you close. Apps receive this message when the user is about to end the session (log out) or when someone calls ExitWindows. Apps are suppose to prepare for imminent death. Typically this means presenting a dialog that says something like, "Um, pardon me, but the system is about to implode and if you want to save the last ten hours of changes you've made, this would be a good time; would you like to save now? (Yes/No/Cancel)." WM_QUERYENDSESSION can even reject death (for example if the user chooses Cancel), in which case life goes on. In code, it looks like this:
DWORD bOKToKill = FALSE;
SendMessageTimeout(hwnd, WM_QUERYENDSESSION, 0, 0,
SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 100, &bOKToKill);
if (bOKToKill) {
// post WM_CLOSE and wait, etc.
}
      It's important to use SendMessageTimeout, not SendMessage, in case the process you're trying to close is hung. SMTO_NOTIMEOUTIFNOTHUNG is a flag that's only available in Windows 2000 and Windows XP that says, "don't timeout if the thread isn't hung." In other words, if the thread is processing normally then wait forever so the user can read the dialog and decide what to do. When the user makes his or her final decision, SendMessageTimeout will return with bOKToKill set appropriately. Naturally, all this assumes the other apps are well-behaved and process WM_QUERYENDSESSION as they're supposed to, which isn't always the case.
      I wrote a program, kp.exe (see Figure 6), to kill a process just like tskill. It uses a class CFindKillProcess (see Figure 7) to find and kill the process:
CFindKillProcess fkp;
DWORD pid = fkp.FindProcess("outlook.exe");
fkp.KillProcess(pid);
FindProcess uses CProcessIterator and CProcessModuleIterator from last month's column to iterate the processes, looking for one whose first module (the EXE that started the process) matches the one you want to find:
CProcessIterator itp;
for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
CProcessModuleIterator itm(pid);
HMODULE hModule = itm.First(); // .EXE
if (/* module name = what I'm looking for */) {
return pid;
}
}
      FindProcess looks for "foo" or "foo.exe." If it finds the process, it returns the process ID, which you can then pass to CFindKillProcess::KillProcess. KillProcess encapsulates the close window/terminate logic I just sketched. It uses CMainWindowIterator from last month's column to iterate the main windows of the process (there can be more than one), posts a WM_CLOSE to each, then waits for the process to die. It has a BOOLean parameter that says whether to use TerminateProcess if the app doesn't die willingly. For details, see Figure 7.

Send questions and comments for Paul to cppqa@microsoft.com.
Paul DiLascia is a freelance writer, consultant, and Web/UI designer-at-large. He is the author of Windows++: Writing Reusable Windows Code in C++(Addison-Wesley, 1992). Paul can be reached at askpd@pobox.com or http://www.dilascia.com.

Trackback 0 Comment 0
2008/06/25 16:31

Visual SourceSafe Automaion.

Visual SourceSafe Automation에 대해 자료를 찾아보았다.
VSS 2005 버젼에서  C#코드로 간편히 Automation을 구현할 수 있으나, VSS 6.0은 여전히 COM interface를 사용해서 작업해야 하는 번거로움이.. 쿨럭;

Visual Studio 2005용 자료.
http://msdn.microsoft.com/en-us/library/4d44xhsd(VS.80).aspx

Visual Studo 6.0자료.
http://msdn.microsoft.com/en-us/library/bb509341(VS.80).aspx
6.0용 예제코드가 있어 사라지기 전 첨부해 본다.

또 번외로 VSS 6.0 Automation관련 DLL의 인터페이스를 OLE Viewer로 추적해 보았다.
레지스트리 위치 : HKEY_CLASSES_ROOT\CLSID\{783CD4E4-9D54-11CF-B8EE-00608CC9A71F}

// Generated .IDL file (by the OLE/COM Object Viewer)
//
// typelib filename: SSAPI.DLL

[
  uuid(783CD4E0-9D54-11CF-B8EE-00608CC9A71F),
  version(5.1),
  helpstring("Microsoft SourceSafe 6.0 Type Library"),
  helpfile("ssauto.hlp"),
  helpcontext(00000000),
  custom(DE77BA64-517C-11D1-A2DA-0000F8773CE9, 100663643),
  custom(DE77BA63-517C-11D1-A2DA-0000F8773CE9, 1043226552),
  custom(DE77BA65-517C-11D1-A2DA-0000F8773CE9, Created by MIDL version 6.00.0347 at Wed Jan 22 01:09:11 2003
)

]
library SourceSafeTypeLib
{
    // TLib :     // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046}
    importlib("stdole2.tlb");

    // Forward declare all types defined in this typelib
    interface IVSSItemOld;
    interface IVSSItem;
    interface IVSSItems;
    interface IVSSCheckouts;
    interface IVSSCheckout;
    interface IVSSVersions;
    interface IVSSVersionOld;
    interface IVSSVersion;
    interface IVSSUsers;
    interface IVSSUser;
    interface IVSSDatabaseOld;
    interface IVSSDatabase;
    interface IVSSEventsOld;
    interface IVSSEvents;
    interface IVSS;
    interface IVSSEventHandler;

    typedef [uuid(783CD4EF-9D54-11CF-B8EE-00608CC9A71F), helpstring("SourceSafe operation flags")]
    enum {
        VSSFLAG_USERRONO = 1,
        VSSFLAG_USERROYES = 2,
        VSSFLAG_TIMENOW = 4,
        VSSFLAG_TIMEMOD = 8,
        VSSFLAG_TIMEUPD = 12,
        VSSFLAG_EOLCR = 16,
        VSSFLAG_EOLLF = 32,
        VSSFLAG_EOLCRLF = 48,
        VSSFLAG_REPASK = 64,
        VSSFLAG_REPREPLACE = 128,
        VSSFLAG_REPSKIP = 192,
        VSSFLAG_REPMERGE = 256,
        VSSFLAG_CMPFULL = 512,
        VSSFLAG_CMPTIME = 1024,
        VSSFLAG_CMPCHKSUM = 1536,
        VSSFLAG_CMPFAIL = 2048,
        VSSFLAG_RECURSNO = 4096,
        VSSFLAG_RECURSYES = 8192,
        VSSFLAG_FORCEDIRNO = 16384,
        VSSFLAG_FORCEDIRYES = 32768,
        VSSFLAG_KEEPNO = 0x00010000,
        VSSFLAG_KEEPYES = 0x00020000,
        VSSFLAG_DELNO = 0x00040000,
        VSSFLAG_DELYES = 0x00080000,
        VSSFLAG_DELNOREPLACE = 0x000c0000,
        VSSFLAG_BINTEST = 0x00100000,
        VSSFLAG_BINBINARY = 0x00200000,
        VSSFLAG_BINTEXT = 0x00300000,
        VSSFLAG_DELTAYES = 0x00400000,
        VSSFLAG_DELTANO = 0x00800000,
        VSSFLAG_UPDASK = 0x01000000,
        VSSFLAG_UPDUPDATE = 0x02000000,
        VSSFLAG_UPDUNCH = 0x03000000,
        VSSFLAG_GETYES = 0x04000000,
        VSSFLAG_GETNO = 0x08000000,
        VSSFLAG_CHKEXCLUSIVEYES = 0x10000000,
        VSSFLAG_CHKEXCLUSIVENO = 0x20000000,
        VSSFLAG_HISTIGNOREFILES = 0x40000000
    } VSSFlags;

    typedef [uuid(783CD4ED-9D54-11CF-B8EE-00608CC9A71F), helpstring("SourceSafe file checkout status")]
    enum {
        VSSFILE_NOTCHECKEDOUT = 0,
        VSSFILE_CHECKEDOUT = 1,
        VSSFILE_CHECKEDOUT_ME = 2
    } VSSFileStatus;

    typedef [uuid(783CD4EE-9D54-11CF-B8EE-00608CC9A71F), helpstring("SourceSafe item type")]
    enum {
        VSSITEM_PROJECT = 0,
        VSSITEM_FILE = 1
    } VSSItemType;

    typedef [uuid(2A0DE0E6-2E9F-11D0-9236-00AA00A1EB95), helpstring("SourceSafe rights values")]
    enum {
        VSSRIGHTS_READ = 1,
        VSSRIGHTS_CHKUPD = 2,
        VSSRIGHTS_ADDRENREM = 4,
        VSSRIGHTS_DESTROY = 8,
        VSSRIGHTS_ALL = 15,
        VSSRIGHTS_INHERITED = 16
    } VSSRights;

    [
      odl,
      uuid(783CD4E1-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe item interface"),
      dual,
      oleautomation
    ]
    interface IVSSItemOld : IDispatch {
        [id(0x00000001), propget]
        HRESULT Spec([out, retval] BSTR* pSpec);
        [id(0x00000002), propget]
        HRESULT Binary([out, retval] VARIANT_BOOL* pbBinary);
        [id(0x00000002), propput]
        HRESULT Binary([in] VARIANT_BOOL pbBinary);
        [id(0x00000003), propget]
        HRESULT Deleted([out, retval] VARIANT_BOOL* pbDeleted);
        [id(0x00000003), propput]
        HRESULT Deleted([in] VARIANT_BOOL pbDeleted);
        [id(0x00000004), propget]
        HRESULT Type([out, retval] int* piType);
        [id(0x00000005), propget]
        HRESULT LocalSpec([out, retval] BSTR* pLocal);
        [id(0x00000005), propput]
        HRESULT LocalSpec([in] BSTR pLocal);
        [id(0x00000006), propget]
        HRESULT Name([out, retval] BSTR* pName);
        [id(0x00000006), propput]
        HRESULT Name([in] BSTR pName);
        [id(0x00000007), propget]
        HRESULT Parent([out, retval] IVSSItem** ppIParent);
        [id(0x00000008), propget]
        HRESULT VersionNumber([out, retval] long* piVersion);
        [id(0x00000009), propget]
        HRESULT Items(
                        [in, optional, defaultvalue(0)] VARIANT_BOOL IncludeDeleted,
                        [out, retval] IVSSItems** ppIItems);
        [id(0x0000000a)]
        HRESULT Get(
                        [in, out, optional, defaultvalue("0")] BSTR* Local,
                        [in, optional, defaultvalue(0)] long iFlags);
        [id(0x0000000b)]
        HRESULT Checkout(
                        [in, optional, defaultvalue("")] BSTR Comment,
                        [in, optional, defaultvalue("")] BSTR Local,
                        [in, optional, defaultvalue(0)] long iFlags);
        [id(0x0000000c)]
        HRESULT Checkin(
                        [in, optional, defaultvalue("")] BSTR Comment,
                        [in, optional, defaultvalue("")] BSTR Local,
                        [in, optional, defaultvalue(0)] long iFlags);
        [id(0x0000000d)]
        HRESULT UndoCheckout(
                        [in, optional, defaultvalue("")] BSTR Local,
                        [in, optional, defaultvalue(0)] long iFlags);
        [id(0x0000000e), propget]
        HRESULT IsCheckedOut([out, retval] long* piStatus);
        [id(0x0000000f), propget]
        HRESULT Checkouts([out, retval] IVSSCheckouts** ppICheckouts);
        [id(0x00000010), propget]
        HRESULT IsDifferent(
                        [in, optional, defaultvalue("")] BSTR Local,
                        [out, retval] VARIANT_BOOL* pbDifferent);
        [id(0x00000011)]
        HRESULT Add(
                        [in] BSTR Local,
                        [in, optional, defaultvalue("")] BSTR Comment,
                        [in, optional, defaultvalue(0)] long iFlags,
                        [out, retval] IVSSItem** ppIItem);
        [id(0x00000012)]
        HRESULT NewSubproject(
                        [in] BSTR Name,
                        [in, optional, defaultvalue("")] BSTR Comment,
                        [out, retval] IVSSItem** ppIItem);
        [id(0x00000013)]
        HRESULT Share(
                        [in] IVSSItem* pIItem,
                        [in, optional, defaultvalue("")] BSTR Comment,
                        [in, optional, defaultvalue(0)] long iFlags);
        [id(0x00000014)]
        HRESULT Destroy();
        [id(0x00000015)]
        HRESULT Move([in] IVSSItem* pINewParent);
        [id(0x00000016)]
        HRESULT Label(
                        [in] BSTR Label,
                        [in, optional, defaultvalue("")] BSTR Comment);
        [id(0x00000017), propget]
        HRESULT Versions(
                        [in, optional, defaultvalue(0)] long iFlags,
                        [out, retval] IVSSVersions** pIVersions);
        [id(0x00000018), propget]
        HRESULT Version(
                        [in, optional] VARIANT Version,
                        [out, retval] IVSSItem** ppIItem);
    };

    [
      odl,
      uuid(2A0DE0E7-2E9F-11D0-9236-00AA00A1EB95),
      helpstring("SourceSafe item interface"),
      dual,
      oleautomation
    ]
    interface IVSSItem : IVSSItemOld {
        [id(0x00000019), propget]
        HRESULT Links([out, retval] IVSSItems** ppIItems);
        [id(0x0000001a)]
        HRESULT Branch(
                        [in, optional, defaultvalue("")] BSTR Comment,
                        [in, optional, defaultvalue(0)] long iFlags,
                        [out, retval] IVSSItem** ppIItem);
    };

    [
      odl,
      uuid(783CD4E5-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe items collection interface"),
      dual,
      oleautomation
    ]
    interface IVSSItems : IDispatch {
        [id(0x00000001), propget]
        HRESULT Count([out, retval] long* piCount);
        [id(00000000), propget]
        HRESULT Item(
                        [in] VARIANT sItem,
                        [out, retval] IVSSItem** ppIItem);
        [id(0xfffffffc), restricted, hidden]
        HRESULT _NewEnum([out, retval] IUnknown** ppIEnum);
    };

    [
      odl,
      uuid(8903A770-F55F-11CF-9227-00AA00A1EB95),
      helpstring("SourceSafe checkouts collection interface"),
      dual,
      oleautomation
    ]
    interface IVSSCheckouts : IDispatch {
        [id(0x00000001), propget]
        HRESULT Count([out, retval] long* piCount);
        [id(00000000), propget]
        HRESULT Item(
                        [in] VARIANT sItem,
                        [out, retval] IVSSCheckout** ppICheckout);
        [id(0xfffffffc), restricted, hidden]
        HRESULT _NewEnum([out, retval] IUnknown** ppIEnum);
    };

    [
      odl,
      uuid(783CD4E6-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe checkouts interface"),
      dual,
      oleautomation
    ]
    interface IVSSCheckout : IDispatch {
        [id(0x00000001), propget]
        HRESULT Username([out, retval] BSTR* pUsername);
        [id(0x00000002), propget]
        HRESULT Date([out, retval] DATE* pDate);
        [id(0x00000003), propget]
        HRESULT LocalSpec([out, retval] BSTR* pLocal);
        [id(0x00000004), propget]
        HRESULT Machine([out, retval] BSTR* pMachine);
        [id(0x00000005), propget]
        HRESULT Project([out, retval] BSTR* pProject);
        [id(0x00000006), propget]
        HRESULT Comment([out, retval] BSTR* pComment);
        [id(0x00000007), propget]
        HRESULT VersionNumber([out, retval] long* piVersion);
    };

    [
      odl,
      uuid(783CD4E7-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe versions collection"),
      dual,
      oleautomation
    ]
    interface IVSSVersions : IDispatch {
        [id(0xfffffffc), restricted, hidden]
        HRESULT _NewEnum([out, retval] IUnknown** ppIEnum);
    };

    [
      odl,
      uuid(783CD4E8-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe version information"),
      dual,
      oleautomation
    ]
    interface IVSSVersionOld : IDispatch {
        [id(0x00000001), propget]
        HRESULT Username([out, retval] BSTR* pUsername);
        [id(0x00000002), propget]
        HRESULT VersionNumber([out, retval] long* piVersion);
        [id(0x00000003), propget]
        HRESULT Action([out, retval] BSTR* pAction);
        [id(0x00000004), propget]
        HRESULT Date([out, retval] DATE* pDate);
        [id(0x00000005), propget]
        HRESULT Comment([out, retval] BSTR* pComment);
        [id(0x00000006), propget]
        HRESULT Label([out, retval] BSTR* pLabel);
        [id(0x00000007), propget]
        HRESULT VSSItem([out, retval] IVSSItem** ppIItem);
    };

    [
      odl,
      uuid(2A0DE0E9-2E9F-11D0-9236-00AA00A1EB95),
      helpstring("SourceSafe version information"),
      dual,
      oleautomation
    ]
    interface IVSSVersion : IVSSVersionOld {
        [id(0x00000008), propget]
        HRESULT LabelComment([out, retval] BSTR* pComment);
    };

    [
      odl,
      uuid(2A0DE0E4-2E9F-11D0-9236-00AA00A1EB95),
      helpstring("SourceSafe users collection interface"),
      dual,
      oleautomation
    ]
    interface IVSSUsers : IDispatch {
        [id(0x00000001), propget]
        HRESULT Count([out, retval] long* piCount);
        [id(00000000), propget]
        HRESULT Item(
                        [in] VARIANT sItem,
                        [out, retval] IVSSUser** ppIUser);
        [id(0xfffffffc), restricted, hidden]
        HRESULT _NewEnum([out, retval] IUnknown** ppIEnum);
    };

    [
      odl,
      uuid(2A0DE0E3-2E9F-11D0-9236-00AA00A1EB95),
      helpstring("SourceSafe user object interface"),
      dual,
      oleautomation
    ]
    interface IVSSUser : IDispatch {
        [id(0x00000001)]
        HRESULT Delete();
        [id(0x00000002), propget]
        HRESULT Name([out, retval] BSTR* pName);
        [id(0x00000002), propput]
        HRESULT Name([in] BSTR pName);
        [id(0x00000003), propput]
        HRESULT Password([in] BSTR rhs);
        [id(0x00000004), propget]
        HRESULT ReadOnly([out, retval] VARIANT_BOOL* pReadOnly);
        [id(0x00000004), propput]
        HRESULT ReadOnly([in] VARIANT_BOOL pReadOnly);
        [id(0x00000005), propget]
        HRESULT ProjectRights(
                        [in, optional, defaultvalue("$/")] BSTR Project,
                        [out, retval] long* piRightsOut);
        [id(0x00000005), propput]
        HRESULT ProjectRights(
                        [in, optional, defaultvalue("$/")] BSTR Project,
                        [in] long piRightsOut);
        [id(0x00000006)]
        HRESULT RemoveProjectRights([in] BSTR Project);
    };

    [
      odl,
      uuid(783CD4E2-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe database object interface"),
      dual,
      oleautomation
    ]
    interface IVSSDatabaseOld : IDispatch {
        [id(0x00000001)]
        HRESULT Open(
                        [in, optional, defaultvalue("")] BSTR SrcSafeIni,
                        [in, optional, defaultvalue("")] BSTR Username,
                        [in, optional, defaultvalue("")] BSTR Password);
        [id(0x00000002), propget]
        HRESULT SrcSafeIni([out, retval] BSTR* pSrcSafeIni);
        [id(0x00000003), propget]
        HRESULT DatabaseName([out, retval] BSTR* pDatabaseName);
        [id(0x00000004), propget]
        HRESULT Username([out, retval] BSTR* pUsername);
        [id(0x00000005), propget]
        HRESULT CurrentProject([out, retval] BSTR* pPrj);
        [id(0x00000005), propput]
        HRESULT CurrentProject([in] BSTR pPrj);
        [id(0x00000006), propget]
        HRESULT VSSItem(
                        [in] BSTR Spec,
                        [in, optional, defaultvalue(0)] VARIANT_BOOL Deleted,
                        [out, retval] IVSSItem** ppIVSSItem);
    };

    [
      odl,
      uuid(2A0DE0E2-2E9F-11D0-9236-00AA00A1EB95),
      helpstring("SourceSafe database object interface"),
      dual,
      oleautomation
    ]
    interface IVSSDatabase : IVSSDatabaseOld {
        [id(0x00000007)]
        HRESULT AddUser(
                        [in] BSTR User,
                        [in] BSTR Password,
                        [in] VARIANT_BOOL ReadOnly,
                        [out, retval] IVSSUser** ppIUser);
        [id(0x00000008), propget]
        HRESULT User(
                        [in] BSTR Name,
                        [out, retval] IVSSUser** ppIUser);
        [id(0x00000009), propget]
        HRESULT Users([out, retval] IVSSUsers** ppIUsers);
        [id(0x0000000a), propget]
        HRESULT ProjectRightsEnabled([out, retval] VARIANT_BOOL* pEnabled);
        [id(0x0000000a), propput]
        HRESULT ProjectRightsEnabled([in] VARIANT_BOOL pEnabled);
        [id(0x0000000b), propget]
        HRESULT DefaultProjectRights([out, retval] long* pRights);
        [id(0x0000000b), propput]
        HRESULT DefaultProjectRights([in] long pRights);
    };

    [
      uuid(783CD4E3-9D54-11CF-B8EE-00608CC9A71F),
      noncreatable
    ]
    coclass VSSItem {
        [default] interface IVSSItem;
        interface IVSSItemOld;
    };

    [
      uuid(783CD4EC-9D54-11CF-B8EE-00608CC9A71F),
      noncreatable
    ]
    coclass VSSVersion {
        [default] interface IVSSVersion;
    };

    [
      uuid(2A0DE0E0-2E9F-11D0-9236-00AA00A1EB95),
      noncreatable
    ]
    coclass VSSCheckout {
        [default] interface IVSSCheckout;
    };

    [
      uuid(783CD4E4-9D54-11CF-B8EE-00608CC9A71F)
    ]
    coclass VSSDatabase {
        [default] interface IVSSDatabase;
        interface IVSSDatabaseOld;
    };

    [
      uuid(2A0DE0E5-2E9F-11D0-9236-00AA00A1EB95),
      noncreatable
    ]
    coclass VSSUser {
        [default] interface IVSSUser;
    };

    [
      odl,
      uuid(783CD4E9-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe event interface")
    ]
    interface IVSSEventsOld : IUnknown {
        HRESULT _stdcall BeforeAdd(
                        [in] IVSSItem* pIPrj,
                        [in] BSTR Local,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterAdd(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local);
        HRESULT _stdcall BeforeCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local);
        HRESULT _stdcall BeforeCheckin(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterCheckin(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local);
        HRESULT _stdcall BeforeUndoCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterUndoCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local);
        HRESULT _stdcall BeforeRename(
                        [in] IVSSItem* pIItem,
                        [in] BSTR NewName,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterRename(
                        [in] IVSSItem* pIItem,
                        [in] BSTR OldName);
        HRESULT _stdcall BeforeBranch(
                        [in] IVSSItem* pIItem,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterBranch([in] IVSSItem* pIItem);
        HRESULT _stdcall BeforeEvent(
                        [in] long iEvent,
                        [in] IVSSItem* pIItem,
                        [in] BSTR Str,
                        [in] VARIANT var,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterEvent(
                        [in] long iEvent,
                        [in] IVSSItem* pIItem,
                        [in] BSTR Str,
                        [in] VARIANT var);
    };

    [
      odl,
      uuid(2A0DE0E8-2E9F-11D0-9236-00AA00A1EB95),
      helpstring("SourceSafe event interface")
    ]
    interface IVSSEvents : IUnknown {
        HRESULT _stdcall BeforeAdd(
                        [in] IVSSItem* pIPrj,
                        [in] BSTR Local,
                        [in] BSTR Comment,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterAdd(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [in] BSTR Comment);
        HRESULT _stdcall BeforeCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [in] BSTR Comment,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [in] BSTR Comment);
        HRESULT _stdcall BeforeCheckin(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [in] BSTR Comment,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterCheckin(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [in] BSTR Comment);
        HRESULT _stdcall BeforeUndoCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterUndoCheckout(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Local);
        HRESULT _stdcall BeforeRename(
                        [in] IVSSItem* pIItem,
                        [in] BSTR NewName,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterRename(
                        [in] IVSSItem* pIItem,
                        [in] BSTR OldName);
        HRESULT _stdcall BeforeBranch(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Comment,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterBranch(
                        [in] IVSSItem* pIItem,
                        [in] BSTR Comment);
        HRESULT _stdcall BeginCommand(
                        [in] long unused,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall EndCommand([in] long unused);
        HRESULT _stdcall BeforeEvent(
                        [in] long iEvent,
                        [in] IVSSItem* pIItem,
                        [in] BSTR Str,
                        [in] VARIANT var,
                        [out, retval] VARIANT_BOOL* pbContinue);
        HRESULT _stdcall AfterEvent(
                        [in] long iEvent,
                        [in] IVSSItem* pIItem,
                        [in] BSTR Str,
                        [in] VARIANT var);
    };

    [
      odl,
      uuid(783CD4EB-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe application interface"),
      dual,
      oleautomation
    ]
    interface IVSS : IDispatch {
        [id(0x00000001), propget]
        HRESULT VSSDatabase([out, retval] IVSSDatabase** ppIVSSDatabase);
    };

    [
      odl,
      uuid(783CD4EA-9D54-11CF-B8EE-00608CC9A71F),
      helpstring("SourceSafe event interface")
    ]
    interface IVSSEventHandler : IUnknown {
        HRESULT _stdcall Init([in] IVSS* pIVSS);
    };

    [
      uuid(2A0DE0E1-2E9F-11D0-9236-00AA00A1EB95),
      noncreatable
    ]
    coclass VSSApp {
        [default] interface IVSS;
        [default, source] interface IVSSEvents;
        [source] interface IVSSEventsOld;
    };
};


Trackback 0 Comment 0
2008/06/18 11:33

Jay Kim의 광우병 관련 영상~




동영상 정말 잘 만들었네요.
요즘 촛불의 향방도 모호하고, 장마도 시작 되었고, 예전 처럼 많은 참여가 없다고 하는데 동영상을 보고
다시 한 번 경각심을 가져야 할 것 같습니다.

정부에서 시민들 정신 못차리게 할려고 일을 더 벌리는 것 같습니다.
대한민국 헌법 1조...

제1조
① 대한민국은 민주공화국이다.
② 대한민국의 주권은 국민에게 있고, 모든 권력은 국민으로부터 나온다.


Trackback 0 Comment 0
2008/06/05 14:49

좀 더 나은 enum 사용법.

Effective c++에서 강조하듯이 제 경우 #define대신 enum을 즐겨쓰는 편입니다.
구글링을 하다가 다음과 같이 enum을 사용하는 것을 보고 퍽이나 괜찮다 생각되 포스팅 해 봅니다.

요약하자면 아래와 같은 코드 대신
enum AIAction
{
AIActionEnter,
AIActionExit,
AIActionStop,
AIActionWalk,
AIActionRun,
};
제 경우 위와같이 쓰면서 접두어 고민을 무척 많이 했었는데요,
아래와 같이 namespace를 사용한 코드를 보면 보다 간결해 진 것을 알 수 있습니다.
namespace GameFlowType
{
enum Enum
{
Invalid,
Run,
Exit,
Restart,
Restore,
};
}

또  위 글의 덧글을 보니 c++0x에서  Strongly typed enumerations이 추가되었네요.

Trackback 0 Comment 1
2008/06/05 14:25

C++ Unit Test Framework.

TDD에 관한 책을 읽긴 했지만, 여전히 실천은 안하고 있습니다.
그래서 오늘은 c++ 유닛 테스팅 도구엔 어떤것이 있는지 알아볼까 합니다.
대충 살펴보고 하나 찍어서 시도해 보려합니다.

일단 서핑해서 알아보니 UnitTest++ , CppUnit, CppUnitLiteBoost unit test 라이브러리 , WinUnit등등이 있습니다. N모사에 근무하는 허모군 이야기에 자신은 WinUnit을 쓰는데 쓸만 하다고 합니다.
구글링 해보니 어떤사람이 각 c++ 유닛 테스팅 도구에 대해 비교한 글도 있네요. 하지만 글 쓴 시점이 2004년 12월이라 지금과는 많이 변했겟지요? ^^;
UnitTest++의 경우는 국내 개발자 한 분께서 VisualUnitTest++이라는 Visual studio 2005, 2008용 add-in도 제작중이시네요.

과연 저렇게 많은 것 들 중에 어떤 것을 취할것인가...
To be continued....








Trackback 0 Comment 1
2008/06/05 12:57

엑스파일..

내가 너무도 좋아했던 드라마 엑스파일이 영화로~~
보고싶어요 멀더! 스컬리!!!



Trackback 0 Comment 0
2008/06/04 16:50

CriticalSection Block (Synchronized block in C++)

보통 데드락 문제를 해결해기 위해 Critical Section을 사용할 때, Locking클래스를 제작하여 지역객체 소멸을 통해 안전한 코드를 보장하곤 합니다.

하지만, 아래와 같은 지역 객체 소멸을 통한 코드보다는..

ACriticalSec g_cs;
DWORD WINAPI ThreadProc1( LPVOID lpParameter )
{
    ....
   {
        AutoLock _cs(&g_cs);
        ..do something..
    }
    ....
}

아래와 같은 코드가 더 직관적이죠. 아닌가? (-_-')

ACriticalSec g_cs;
DWORD WINAPI ThreadProc1( LPVOID lpParameter )
{
    ...
    SYNCRONIZED_BLOCK(&g_cs)
    {
        ...do something...
    }
    ...
}

그래서 아래와 같은 클래스로 만들어 보았습니다.
http://www.codeproject.com/KB/threads/synchronized.aspx
에서 힌트를 얻었는데, if문에서 새로운 변수가 선언 가능하다는 특징을 이용한 것입니다.

#pragma once
class ACriticalSec
{
    ACriticalSec(const ACriticalSec &refCritSec);
    ACriticalSec &operator=(const ACriticalSec &refCritSec);
    CRITICAL_SECTION m_CritSec;

public:
    ACriticalSec()
    {
        ::InitializeCriticalSection(&m_CritSec);
    };

    ~ACriticalSec()
    {
        ::DeleteCriticalSection(&m_CritSec);
    };

    void Lock()
    {
        ::EnterCriticalSection(&m_CritSec);
    };

    void Unlock()
    {
        ::LeaveCriticalSection(&m_CritSec);
    };

};

class AutoLock
{
    AutoLock(const AutoLock &refAutoLock);
    AutoLock &operator=(const AutoLock &refAutoLock);

protected:
    ACriticalSec* m_pLock;

public:
    AutoLock(ACriticalSec* pLock) : m_pLock(pLock)
    {
        m_pLock->Lock();
    };

    ~AutoLock()
    {
        m_pLock->Unlock();
    };

    operator bool()
    {
        return false;
    }
};

#define SYNCRONIZED_BLOCK(CS)  if(AutoLock _lock = CS) {} else

// 위 synchronized define 구문은 c++에서 데이터 락킹을 아래와 같이 쓸 수 있도록 하기 위함.
// 물론 지역객체 소멸을 통한 관용구로 구현할수도 있지만, 아래코드가 더 직관적이고 예쁜 듯 하다.

// ACriticalSec myCs;
// SYNCRONIZED_BLOCK(someCriticalSection)
// {
//     ...
// }



만약 위 코드의 synchronized가 전개되면 다음과 같은 코드가 되겠지요.

ACriticalSec g_cs;
DWORD WINAPI ThreadProc1( LPVOID lpParameter )
{
    ...
    if(AutoLock _lock = CS) {} else
   {
        ...do something...
   }
    ...
}

위 코드에서 _lock객체는 else 블락에서 자동 해제되게 됩니다.



Trackback 0 Comment 1