출처 : http://blog.happydong.kr/189

 

C#으로 개발을 하다보면 다양한 상황에서 디버깅을해서 처리 값을 확인해야 하는 일이 생긴다. Output Value를 확인하다든지... 정확한 값이 세팅되었다 든지..., 더미값(쓰레기값)을 세팅해서 프로그램을 테스트 한다던지... 등등의 여러가지 상황에서 디버깅 값을 확인해야 할 일들이 빈번하게 있기 마련이다. 그리고 이렇게 디버깅한 내용은 릴리즈 할때는 적용이 안되어야 하는 것이 맞다. 그래서 디버깅 코드를 짤때에는 디버그모드일때와 릴리지모드일때 실행되야할 코드를 적절히 나눠서 짜야한다. 이렇게 구분하기 위해서는  #if #endifConditional Attribute를 적절하게 사용하는 것이 좋다. 
처음 개발을 시작했을 때는 생각해보자!! 예전 같았으면 프로그램 소스를 짜면서 디버깅소스를 코드로 같이 짜고 디버그 모드(Debug Mode)에서 확인하고 필요없을때(릴리즈때)는 주석처리하면서 했을 것이다. 물론, 머리가 좋은 사람들은 이런식으로 처리안 했을 것이다. 그러나 프로그램을 처음 접하면서 배우는 것이 디버깅하는 방법보다, 주석을 먼저 배우기때문에 이런 불편한 방법을 사용하는 초보 개발자들이 몇몇 있을 것이다. 물론, 나도 처음 배울때 이랬다.

주석으로 처리하는 잘못된 예

/*  릴리즈때는 사용하지 않음.
            MessageBox.Show("Test");
  */

위 코드의 내용 처럼 릴리즈 모드(Release Mode)일때와 디버그 모드(Debug Mode)일때를 확인해서 처리해야하는 경우가 있다면 바보같이 주석처리해가면서 처리하지말고 #if #end와 Conditional Attribute를 이용하자!!

1. #if #endif 사용

이는 메소드 내부의 간단한 처리를 확인 할때 사용하는 것이 적절한 것 같다. 사용 방법은 아래와 같다.

private void InitializeView()
{

#if DEBUG
	// 처리된 결과의 값을 찍어 봅니다. 
	Debug.WriteLine("Value1");
	Debug.WriteLine("Value2");
#endif
}

#if #endif를 많이 사용하면 코드가 조금 지저분해 질수 있으니 적절하게 적당히 사용하는 것이 좋을 것 같다. 

 

 

2. Conditional Attribute 사용

이는 메소드 형태로 사용할수 있으면 빌드모드에 따라 해당 메소드를 호출할지 않할지를 결정할수 있다. 사용 방법은 아래와 같다.

Conditional Attribute

private void InitializeView()
{
	... 내용 생략...
	DebugMsg();
}
[Conditional("DEBUG")]
public void DebugMsg()
{
	MessageBox.Show("Conditional Test");
}

 

InitializeView메소드안에 보면 DebugMsg라는 메소드를 호출하고 있는데, 빌드모드가 디버그이면 해당 메소드를 호출할 것이고, 릴리즈일 경우 호출되지 않을 것이다. 그리고 Conditional은 다중 지정이 가능하다. 즉, [Conditional("DEBUG"), Conditional("TRACE")] 이런식으로 가능하다.

#if #endif와 Conditional Attribute를 적절히 사용하면 보다 깔끔한 코드, 디버그모드와 릴리지모드를 나눠서 코드를 정리할수 있을 것이다. 물론, #if #endif보다는 Conditional Attribute를 활용하는 쪽이 보다 깔끔한 소스를 짤수 있을 것이다. Conditional를 선언한 메소드들을 한클래스에 모아서 사용하는 것도 적절하다 볼수 있다.

참고 )
프로젝트의 프로퍼티(Properties)메뉴에 들어가, 빌드(Build) 옵션에서 해당 빌드모드의 내용을 체크할수 있다.

 

출처 : http://blog.happydong.kr/189

별출처 : MSDN(http://msdn.microsoft.com/ko-kr/library/bb397679.aspx)

 

 

<?XML:NAMESPACE PREFIX = [default] http://www.w3.org/1999/xhtml NS = "http://www.w3.org/1999/xhtml" />이러한 변환은 예를 들어 명령줄 인수에서 숫자 입력을 가져올 때 유용할 수 있습니다. 비슷한 메서드로 문자열을 float 또는 long 등의 다른 숫자 형식으로 변환할 수도 있습니다. 다음 표에서는 이러한 메서드를 보여 줍니다.

숫자 형식

방법

decimal

ToDecimal(String)

float

ToSingle(String)

double

ToDouble(String)

short

ToInt16(String)

int

ToInt32(String)

long

ToInt64(String)

ushort

ToUInt16(String)

uint

ToUInt32(String)

ulong

ToUInt64(String)

예제

 


이 예제에서는 ToInt32(String) 메서드를 호출하여 입력 stringint로 변환합니다. 프로그램이이 메서드에 의해 throw 될 수 있는 두 개의 가장 일반적인 예외를 catch 합니다. FormatExceptionOverflowException. 정수 저장소 위치를 오버플로하지 않고 숫자를 증가시킬 수 있는 경우 프로그램에서 결과에 1을 더하여 출력을 인쇄합니다.

C#

static void Main(string[] args)
{
    int numVal = -1;
    bool repeat = true;

    while (repeat == true)
    {
        Console.WriteLine("Enter a number between −2,147,483,648 and +2,147,483,647 (inclusive).");

        string input = Console.ReadLine();

        // ToInt32 can throw FormatException or OverflowException.
        try
        {
            numVal = Convert.ToInt32(input);
        }
        catch (FormatException e)
        {
            Console.WriteLine("Input string is not a sequence of digits.");
        }
        catch (OverflowException e)
        {
            Console.WriteLine("The number cannot fit in an Int32.");
        }
        finally
        {
            if (numVal < Int32.MaxValue)
            {
                Console.WriteLine("The new value is {0}", numVal + 1);
            }
            else
            {
                Console.WriteLine("numVal cannot be incremented beyond its current value");
            }
        }
        Console.WriteLine("Go again? Y/N");
        string go = Console.ReadLine();
        if (go == "Y" || go == "y")
        {
            repeat = true;
        }
        else
        {
            repeat = false;
        }
    }
    // Keep the console open in debug mode.
    Console.WriteLine("Press any key to exit.");
    Console.ReadKey();    
}
// Sample Output:
// Enter a number between -2,147,483,648 and +2,147,483,647 (inclusive).
// 473
// The new value is 474
// Go again? Y/N
// y
// Enter a number between -2,147,483,648 and +2,147,483,647 (inclusive).
// 2147483647
// numVal cannot be incremented beyond its current value
// Go again? Y/N
// Y
// Enter a number between -2,147,483,648 and +2,147,483,647 (inclusive).
// -1000
// The new value is -999
// Go again? Y/N
// n
// Press any key to exit.

string 을 int로 변환하는 또 다른 방법은 System.Int32 구조체의 Parse 또는 TryParse 메서드를 사용하는 것입니다. ToUInt32 메서드는 Parse를 내부적으로 사용합니다. 문자열이 올바른 형식이 아닌 경우 Parse는 예외를 throw하는 반면, TryParse는 예외를 throw하지 않고false를 반환합니다. 다음 예제에서는 ParseTryParse에 대한 호출이 성공하는 경우와 실패하는 경우를 모두 보여 줍니다.

C#

int numVal = Int32.Parse("-105");
Console.WriteLine(numVal);
// Output: -105

C#

// TryParse returns true if the conversion succeeded
// and stores the result in the specified variable.
int j;
bool result = Int32.TryParse("-105", out j);
if (true == result)
    Console.WriteLine(j);
else
    Console.WriteLine("String could not be parsed.");
// Output: -105

C#

try
{
    int m = Int32.Parse("abc");
}
catch (FormatException e)
{
    Console.WriteLine(e.Message);
}
// Output: Input string was not in a correct format.

C#

string inputString = "abc";
int numValue;
bool parsed = Int32.TryParse(inputString, out numValue);

if (!parsed)
    Console.WriteLine("Int32.TryParse could not parse '{0}' to an int.\n", inputString);

// Output: Int32.TryParse could not parse 'abc' to an int.

별Link : How to Integrate Excel in a Windows Form Application using the WebBrowser

 

 

Sample Image - Embedding_Excel.jpg

Introduction

With Automation, you are able to drive any Office application from your .NET application. This is really powerful. It may happen that one time, you would like to integrate such an application (Excel, for example) in your own application, and handle it like a control. A first approach has already been published on The Code Project (see the Background section in this article). The other method I will describe here uses the Microsoft WebBrowser control as a host for the document.

Background

You can study Anup Shinde's article. His method works fine. Instead of the WebBrowser control, it is based on Windows Win32 API.

If you are interested in the original publication of the WebBrowser method, you can see the Microsoft KB.

Starting from scratch

Create a new form MyForm, and add a new WebBrowser control, named webBrowser1. Add the m_ExcelFileNamefield :

Collapse | Copy Code

// Contains the path to the workbook file
private string m_ExcelFileName="test.xls"; // Replace here with an existing file

Then create a function OpenFile like this :

Collapse | Copy Code

public void OpenFile(string filename) 
{
    // Check the file exists
    if(!System.IO.File.Exists(filename)) throw new Exception();
        m_ExcelFileName=filename;
    // Load the workbook in the WebBrowser control
    this.webBrowser1.Navigate(filename,false);
}

You can try and run your application, giving the filename an existing excel file path. You'll see that it works perfectly. Really easy, don't you think?

In fact, you will quickly get into trouble if you try to run the application a second time with the same Excel file. An error message tells you that your file is already in use. This may be strange because you think that you closed your application, and you did. So where is the problem?

Let's see what happened in the background. While the WebBrowser was navigating, it opened an invisible Excel application, and loaded the workbook inside it. And when you closed your application, the WebBrowser didn't close either its Excel application or the workbook. So we must do it, and this is the most difficult part of our job.

Solving the problem step by step

Before further reading, you have to load the following Office COM library references for Office Automation :

  • Microsoft Excel 11.0 Object Library
  • Microsoft Office 11.0 Object Library

and use them in your file :

Collapse | Copy Code

using Microsoft.Office.Core;
using Microsoft.Office.Interop.Excel;

You'll need these assemblies too :

Collapse | Copy Code

using System.Runtime.InteropServices;
using System.Reflection;
using System.Runtime.InteropServices.ComTypes;

Declare these two Excel fields :

Collapse | Copy Code

// Contains a reference to the hosting application
private Microsoft.Office.Interop.Excel.Application m_XlApplication=null;
// Contains a reference to the active workbook
private Workbook m_Workbook=null;

Before trying to close the workbook, we need a handle on it. For convenience, the best moment to do this is just after the document has been loaded in the WebBrowser. So we have to generate a webBrowser1_Navigated event handler and its matching function, like this :

Collapse | Copy Code

private void webBrowser1_Navigated(object sender,WebBrowserNavigatedEventArgs e) 
{
    // Creation of the workbook object
    if((m_Workbook=RetrieveWorkbook(m_ExcelFileName))==null)return;
    // Create the Excel.Application
    m_XlApplication=(Microsoft.Office.Interop.Excel.Application)m_Workbook.Application;
}

Then we define the RetrieveWorkbook function. It is based on two imported Win32 API functions, that retrieve all the programs that are running on our computer. Our job is to search among them the one that is working with the workbook that names xlfile. The code is like this :

Collapse | Copy Code

[DllImport("ole32.dll")] static extern int GetRunningObjectTable
                (uint reserved,out IRunningObjectTable pprot);
[DllImport("ole32.dll")] static extern int CreateBindCtx(uint reserved,out IBindCtx pctx);

public Workbook RetrieveWorkbook(string xlfile) 
{
        IRunningObjectTable prot=null;
        IEnumMoniker pmonkenum=null;
        try 
        {
            IntPtr pfetched=IntPtr.Zero;
            // Query the running object table (ROT)
            if(GetRunningObjectTable(0,out prot)!=0||prot==null) return null;
            prot.EnumRunning(out pmonkenum); pmonkenum.Reset();
            IMoniker[] monikers=new IMoniker[1];
            while(pmonkenum.Next(1,monikers,pfetched)==0) 
            {
                IBindCtx pctx; string filepathname;
                CreateBindCtx(0,out pctx);
                 // Get the name of the file
                 monikers[0].GetDisplayName(pctx,null,out filepathname);
                 // Clean up
                 Marshal.ReleaseComObject(pctx);
                 // Search for the workbook
                 if(filepathname.IndexOf(xlfile)!=-1) 
                 {
                     object roval;
                     // Get a handle on the workbook
                     prot.GetObject(monikers[0],out roval);
                     return roval as Workbook;
                 }
              }
         } 
         catch 
         {
             return null;
         } 
         finally 
         {
             // Clean up
             if(prot!=null) Marshal.ReleaseComObject(prot);
             if(pmonkenum!=null) Marshal.ReleaseComObject(pmonkenum);
         }
         return null;
}

Now we can write the code involved to close the background Excel application, while overriding the OnClose() event :

Collapse | Copy Code

protected override void OnClosed(object sender, EventArgs e) 
{
    try 
    {
        // Quit Excel and clean up.
        if(m_Workbook!=null) 
        {
            m_Workbook.Close(true,Missing.Value,Missing.Value);
            System.Runtime.InteropServices.Marshal.ReleaseComObject
                                    (m_Workbook);
            m_Workbook=null;
        }
        if(m_XlApplication!=null) 
        {
            m_XlApplication.Quit();
            System.Runtime.InteropServices.Marshal.ReleaseComObject
                                (m_XlApplication);
            m_XlApplication=null;
            System.GC.Collect();
        }
    } 
    catch 
    {
        MessageBox.Show("Failed to close the application");
    }
}

Using the code

You can use the code as written upper. Otherwise, it may be interesting to embed all the stuff in a .NET control. You'll be able to manage CommandBars, Menus, etc. inside the control. You will find some code in the downloadable package section.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Temporary Directory

string strTempPath = System.IO.Path.GetTempPath();

 

Temporary FileName

string strTempFileName = System.IO.Path.GetTempFileName();

오류가 발생된 환경은 아래와 같으며, 아래 환경기준으로 설명하겠습니다.

  • OS : Microsoft Windows 7 Pro. 64bit
  • VisualStudio 2012
  • Team Foundation Server 2012

PC명을 변경하였을시 Team Foundation Server와 VisualStudio 팀프로젝트 이용시 오류가 발생 된다.

 

해당 솔루션을 오픈 시 PC명이 변경되었으니 “tf workspaces /updateComputerName:oldComputerName” 명령을 이용하여 변경하라고 한다.

(이 부분은 벌써 처리한 후라서 기억이 가물가물합니다.)

 

실행창을 열어 “cmd.exe”를 실행합니다.

저 명령대로 “tf workspaces”라고 실행하여 보면 경로를 찾을 수 없다고 나옵니다.

사용자별로 틀리겠지만 “Windows 7 64bit”환경에서는 “C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\” 경로에 tf.exe가 있습니다.

 

그래서 전체 경로를 포함한 명령을 실행하여 현재 Workspace들을 확인합니다.

C:\>"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\tf" workspaces

변경하기 위해서는

C:\>"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\tf" workspaces /updateComputerName:{이전 PC명}

이라고 하면 여기서도 오류를 발생합니다.

/updateComputerName 또는 /updateUserName을 지정할 때에는 /collection 옵션을 지정해야 합니다.

그럼 최종 명령은

"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\tf" workspaces /updateComputerName:JHPARK-NOTE /collection:http://tfs2012.hi-techeng.co.kr:8080/tfs/HITECHENG

C:\>"C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\tf" workspaces /updateComputerName:{이전 PC명} /collection:http://{Team Foondation Server URL}:{Port(기본:8080)}/tfs/{팀 프로젝트 컬렉션}

그 이후 이전 PC명으로 된 Workspace를 절대 삭제하지 않는것을 권장합니다.

혹여 삭제를 하였을 경우 새로 솔루션을 소수제어에 추가하고 충돌해결을 해야 하는 번거러운 작업을 경험하게 되실 겁니다.(제가 그랬습니다.)

대략 적으로 설명을 하였는데 이해가 되었는지 모르겠습니다. 저만의 방식과 해결후 정리 개념으로 작성하다보니…

 

기타 참고 문헌 :

(한글) http://msdn.microsoft.com/ko-kr/library/54dkh0y3%28v=vs.100%29   

(영문) http://msdn.microsoft.com/en-us/library/54dkh0y3%28v=vs.100%29.aspx

사전에 Exchange Web Services Managed API(SDK)가 설치 되어져 있어야 하며

프로젝트 참조에 Microsoft.Exchange.WebServices (C:\Program Files\Microsoft\Exchange\Web Services\1.2\Microsoft.Exchange.WebServices.dll)를 추가하시기 바랍니다.

using Microsoft.Exchange.WebServices.Data;

본 샘플은 제목만 읽어온것이며, 경우에 따라서는 메소드를 잘 활용하시면 여러가지 정보를 읽어 올 수 있습니다.

소스만 보셔도 쉽게 이해가 가능 할 실 겁니다.

[????] 된 부분은 사용자에 맞게 변경하시기 바랍니다.

Exchange 서버 버전은 2010 SP1입니다.

8라인에서 서버에 맞는 버전을 선택하여 주세요. (2010 SP1은 ExchangeVersion.Exchange2010_SP1)

16라인에서 1개만 가져올경우 샘플이며, 크기는 알아서 조절 하세요(new ItemView(1))

string strExchangeDomain = @"[Domain]"; //ex) userpark.net
string strExchangeServerName = string.Format("exchange.{0}", strExchangeDomain); // exchange.userpark.net
string strExchangeUserID = @"[UserID]"; //사용자 ID
string strExchangeUserPs = @"[Password]"; //사용자 Password
string strExchangeMail = string.Format("{0}@{1}", strExchangeUserID, strExchangeDomain);  //ex)userpark@userpark.net
string strExchangeEwsUrl = string.Format("{0}://{1}/EWS/Exchange.asmx", "https", strExchangeServerName);

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);

//두개중 하나 NetworkCredential 또는 WebCredentials
//service.Credentials = new System.Net.NetworkCredential(strExchangeUserID, strExchangeUserPs, strExchangeDomain);
service.Credentials = new WebCredentials(strExchangeUserID, strExchangeUserPs, strExchangeDomain);

service.Url = new Uri(strExchangeEwsUrl);

Microsoft.Exchange.WebServices.Data.FindItemsResults<Microsoft.Exchange.WebServices.Data.Item> findResults = service.FindItems(Microsoft.Exchange.WebServices.Data.WellKnownFolderName.Inbox, new ItemView(1));
foreach (Microsoft.Exchange.WebServices.Data.Item item in findResults.Items)
{
	//if (item.IsNew == true)  //읽지 않은 경우만 가져올 경우
	Console.WriteLine(item.Subject);
}

 

2012/06/25 - [자료실] - Microsoft Exchange Web Service Managed API SDK 1.2.1

출처 : 자작(userpark)

Microsoft Exchange 프로그램을 하기 위한 필수 SDK :  Exchange Web Services Managed API(SDK) 1.2.1

출처 : Microsoft

DataTable간 Join하는 방법입니다.
소스 보시면 쉽게 이해가 가능 하 실 겁니다.
DataGridView를 통해서 최종 결과를 뿌려줍니다.
UI디자인에서 미리 만들어 놓으시기 바랍니다.
그럼 소스는…
DataTable dtUser = new DataTable();
DataTable dtDept = new DataTable();
DataTable dtUserInfo = null;
DataRow drTemp;
//사용자 정보 테이블 - DataTable Column을 추가(Range)
dtUser.Columns.AddRange(new DataColumn[] { 
		new DataColumn {ColumnName = "no", Caption = "Increment", DataType = typeof(int), Unique = true, AutoIncrement = true}
		, new DataColumn {ColumnName = "user_id", Caption = "User ID", DataType = typeof(string), Unique = true, AllowDBNull = false}
		, new DataColumn {ColumnName = "user_name", Caption = "User Name", DataType = typeof(string), AllowDBNull = false}
		, new DataColumn {ColumnName = "dept_no", Caption = "Dept. Code", DataType = typeof(int), DefaultValue = -1}
		, new DataColumn {ColumnName = "is_use", Caption = "IS Use?", DataType = typeof(bool), DefaultValue = true}
	});

/*
 * BEGIN DataRow를 이용한 사용자 정보 추가
 * */
drTemp = dtUser.NewRow();
//AutoIncrement가 0부터 시작하므로 처음값만 1로 강제 부여
drTemp["no"] = 1;
drTemp["user_id"] = "test1";
drTemp["user_name"] = "Tester 1";
drTemp["dept_no"] = 1;
drTemp["is_use"] = true;
dtUser.Rows.Add(drTemp);

drTemp = dtUser.NewRow();
drTemp["user_id"] = "test2";
drTemp["user_name"] = "Tester 2";
drTemp["dept_no"] = 100;
dtUser.Rows.Add(drTemp);

drTemp = dtUser.NewRow();
drTemp["user_id"] = "test3";
drTemp["user_name"] = "Tester 3";
drTemp["dept_no"] = 3;
drTemp["is_use"] = false;
dtUser.Rows.Add(drTemp);

drTemp = dtUser.NewRow();
drTemp["user_id"] = "test4";
drTemp["user_name"] = "Tester 4";
dtUser.Rows.Add(drTemp);
/*
 * END DataRow를 이용한 사용자 정보 추가
 * */

//부서 정보 테이블 - DataTable Column을 추가(Range)
dtDept.Columns.AddRange(new DataColumn[] {
		new DataColumn {ColumnName = "dept_no", Caption = "Dept. Code", DataType = typeof(int), Unique = true, AutoIncrement = true}
		, new DataColumn {ColumnName = "dept_name", Caption = "Dept. Name", DataType = typeof(string), DefaultValue = string.Empty, AllowDBNull = true}
	});

/*
 * BEGIN DataRow를 이용한 부서 정보 추가
 * */
drTemp = dtDept.NewRow();
//AutoIncrement가 0부터 시작하므로 처음값만 1로 강제 부여
drTemp["dept_no"] = 1;
drTemp["dept_name"] = "IT Team";
dtDept.Rows.Add(drTemp);

drTemp = dtDept.NewRow();
drTemp["dept_name"] = "Management Team";
dtDept.Rows.Add(drTemp);

drTemp = dtDept.NewRow();
drTemp["dept_name"] = "Project Management Team";
dtDept.Rows.Add(drTemp);
/*
 * END DataRow를 이용한 부서 정보 추가
 * */

/*
 * BEGIN JOIN 이후 DataView등에 사용할 최종 사용자 정보 DataTable 설정
 * */
//기존 사용자 정보 테이블 구조 및 스키마만 복사(데이터는 복사하지 않음)
dtUserInfo = dtUser.Clone();
//Join으로 추가할 부서 테이블에서 부서명에 해당되는 컬럼 추가
dtUserInfo.Columns.Add(new DataColumn { ColumnName = "dept_name", Caption = "Dept. Name", DataType = typeof(string), DefaultValue = string.Empty, AllowDBNull = true });
//Join 성공 여부 컬럼 추가
dtUserInfo.Columns.Add("is_join_dept", typeof(bool));
/*
 * END JOIN 이후 DataView등에 사용할 최종 사용자 정보 DataTable 설정 
 * */

/*
 * BEGIN 사용자 테이블과 부서 테이블간 JOIN후 최종 사용자 정보 DataTable에 반영
 * */
//var : Variable의 약자, C# 3.0부터 추가된 타입이 없는 변수, 초기에 대입되는 값에 의하여 변수의 형식이 결정 됨(int, string, double ... 등 활용 가능)
//      여기서는 IEnumerable타입으로 이용
var query =
			from u in dtUser.AsEnumerable()
			join d in dtDept.AsEnumerable()
				//on (int)o["area_index_no"] equals (int)(decimal)e["area_index_no"] into j
			on
				u["dept_no"] equals d["dept_no"]
			into j
			from jList in j.DefaultIfEmpty()
			select new
			{
				no = u["no"]
				,
				user_id = u["user_id"].ToString()
				,
				user_name = u["user_name"].ToString()
				,
				dept_no = u["dept_no"]
				,
				dept_name = (jList != null ? jList["dept_name"] : string.Empty)
				,
				is_use = Convert.ToBoolean(u["is_use"])
				,
				is_join_dept = (bool)(jList == null ? true : false)
			};

foreach (var v in query)
{
	drTemp = dtUserInfo.NewRow();
	drTemp.BeginEdit(); //생략가능
	drTemp["no"] = v.no;
	drTemp["user_id"] = v.user_id;
	drTemp["user_name"] = v.user_name;
	drTemp["dept_no"] = v.dept_no;
	drTemp["dept_name"] = v.dept_name;
	drTemp["is_use"] = v.is_use;
	drTemp["is_join_dept"] = v.is_join_dept;
	drTemp.EndEdit(); //생략가능
	dtUserInfo.Rows.Add(drTemp);
}
/*
 * END 사용자 테이블과 부서 테이블간 JOIN후 최종 사용자 정보 DataTable에 반영
 * */

//DataGridView에 반영
dataGridView1.DataSource = dtUser;
dataGridView2.DataSource = dtDept;
dataGridView3.DataSource = dtUserInfo;

출처 : 자작(userpark)

그냥 설명은 무시하고 예제 소스로 그냥 진행합니다.

DataSet이 아닌 일반 DataTable을 이용하는 방법도 동일합니다.

 

DataSet 생성

DataSet ds = new DataSet();
DataRow dr = null;
DataTable dt01 = new DataTable();
dt01.TableName = "Test01";
dt01.Columns.AddRange(new DataColumn[] {
        new DataColumn { ColumnName ="no", Caption = "일련번호", DataType=typeof(int), DefaultValue = 0}
        , new DataColumn { ColumnName ="col", Caption = "컬럼명", DataType=typeof(string), DefaultValue = string.Empty}
        , new DataColumn { ColumnName ="val", Caption = "값", DataType=typeof(string), DefaultValue = string.Empty}
        , new DataColumn { ColumnName ="etc", Caption = "비고", DataType=typeof(string), DefaultValue = string.Empty}
    });
dr = dt01.NewRow();
dr["no"] = 1;
dr["col"] = "COL1";
dr["val"] = "A";
dr["etc"] = "비고1";
dt01.Rows.Add(dr);
dr = dt01.NewRow();
dr["no"] = 2;
dr["col"] = "COL2";
dr["val"] = "B";
dt01.Rows.Add(dr);
dr = dt01.NewRow();
dr["no"] = 3;
dr["col"] = "COL3";
dr["val"] = "C";
dt01.Rows.Add(dr);
dr = dt01.NewRow();
dr["no"] = 4;
dr["col"] = "COL4";
dr["val"] = "D";
dt01.Rows.Add(dr);
dr = dt01.NewRow();
dr["no"] = 5;
dr["col"] = "COL5";
dr["val"] = "가";
dt01.Rows.Add(dr);
dr = dt01.NewRow();
dr["no"] = 6;
dr["col"] = "COL6";
dr["val"] = "나※";
dt01.Rows.Add(dr);
dr = dt01.NewRow();
dr["no"] = 7;
dr["col"] = "COL7";
dr["val"] = "~!@#$%^&*()_+`-={}[]:\";'<>?,./|\\";
dt01.Rows.Add(dr);
dr = dt01.NewRow();
dr["no"] = 8;
dr["col"] = "COL8";

dt01.Rows.Add(dr);
dr = dt01.NewRow();
dt01.Rows.Add(dr);
 
 
DataTable dt02 = new DataTable();
dt02.TableName = "Test02";
dt02.Columns.AddRange(new DataColumn[] {
        new DataColumn { ColumnName ="no", Caption = "일련번호", DataType=typeof(int), AutoIncrement = true}
        , new DataColumn { ColumnName ="etc", Caption = "비고", DataType=typeof(string), DefaultValue = string.Empty}
    });
dr = dt02.NewRow();
dr["etc"] = "비고1";
dt02.Rows.Add(dr);
dr = dt02.NewRow();
dr["etc"] = "비고2";
dt02.Rows.Add(dr);
dr = dt02.NewRow();
dr["etc"] = "비고3";
dt02.Rows.Add(dr);
dr = dt02.NewRow();
dr["etc"] = "비고4";
dt02.Rows.Add(dr);
dr = dt02.NewRow();
dr["etc"] = "비고5";
dt02.Rows.Add(dr);
dr = dt02.NewRow();
dr["etc"] = "비고6";
dt02.Rows.Add(dr);
 
ds.Tables.Add(dt01);
ds.Tables.Add(dt02);

XML 파일로 저장

ds.WriteXmlSchema(@"c:\TestForDS.xsd");
ds.WriteXml(@"c:\TestForDS.xml");

 

XML Stream을 이용하여 String에 담기

System.IO.MemoryStream mStreamXSD = new System.IO.MemoryStream();
System.IO.MemoryStream mStreamXML = new System.IO.MemoryStream();
ds.WriteXmlSchema(mStreamXSD);
mStreamXSD.Seek(0, System.IO.SeekOrigin.Begin);
ds.WriteXml(mStreamXML);
mStreamXML.Seek(0, System.IO.SeekOrigin.Begin);
System.IO.StreamReader srXSD = new System.IO.StreamReader(mStreamXSD);
System.IO.StreamReader srXML = new System.IO.StreamReader(mStreamXML);
string strXSD = srXSD.ReadToEnd();
string strXML = srXML.ReadToEnd();

 

이 방법을 이용하여 Oracle Clob 저장 및 활용

 

=================================================================

참고(출력 파일)

XSD

<?xml version="1.0" standalone="yes"?>
<xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
  <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element name="Test01">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="no" msdata:Caption="일련번호" type="xs:int" default="0" minOccurs="0" />
              <xs:element name="col" msdata:Caption="컬럼명" type="xs:string" default="" minOccurs="0" />
              <xs:element name="val" msdata:Caption="값" type="xs:string" default="" minOccurs="0" />
              <xs:element name="etc" msdata:Caption="비고" type="xs:string" default="" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
        <xs:element name="Test02">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="no" msdata:AutoIncrement="true" msdata:Caption="일련번호" type="xs:int" minOccurs="0" />
              <xs:element name="etc" msdata:Caption="비고" type="xs:string" default="" minOccurs="0" />
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

XML

<?xml version="1.0" standalone="yes"?>
<NewDataSet>
  <Test01>
    <no>1</no>
    <col>COL1</col>
    <val>A</val>
    <etc>비고1</etc>
  </Test01>
  <Test01>
    <no>2</no>
    <col>COL2</col>
    <val>B</val>
    <etc />
  </Test01>
  <Test01>
    <no>3</no>
    <col>COL3</col>
    <val>C</val>
    <etc />
  </Test01>
  <Test01>
    <no>4</no>
    <col>COL4</col>
    <val>D</val>
    <etc />
  </Test01>
  <Test01>
    <no>5</no>
    <col>COL5</col>
    <val>가</val>
    <etc />
  </Test01>
  <Test01>
    <no>6</no>
    <col>COL6</col>
    <val>나※</val>
    <etc />
  </Test01>
  <Test01>
    <no>7</no>
    <col>COL7</col>
    <val>~!@#$%^&amp;*()_+`-={}[]:";'&lt;&gt;?,./|\</val>
    <etc />
  </Test01>
  <Test01>
    <no>8</no>
    <col>COL8</col>
    <val />
    <etc />
  </Test01>
  <Test01>
    <no>0</no>
    <col />
    <val />
    <etc />
  </Test01>
  <Test02>
    <no>0</no>
    <etc>비고1</etc>
  </Test02>
  <Test02>
    <no>1</no>
    <etc>비고2</etc>
  </Test02>
  <Test02>
    <no>2</no>
    <etc>비고3</etc>
  </Test02>
  <Test02>
    <no>3</no>
    <etc>비고4</etc>
  </Test02>
  <Test02>
    <no>4</no>
    <etc>비고5</etc>
  </Test02>
  <Test02>
    <no>5</no>
    <etc>비고6</etc>
  </Test02>
</NewDataSet>

출처 : 자작(userpark)

출처 : http://blog.naver.com/lcg2004?Redirect=Log&logNo=60049785458

참고 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=17&MAEULNo=8&no=117409&ref=117385

Writing to Oracle CLOB fields
using System.Data.OracleClient

만약 당신이 .NET 코더고 오라클을 갖다가 데이터베이스 작업을 한다면, 이번이 적절하게 사용할 수 있는 기회가 될 것이다.^^ 읽으면서 커멘트도 달아주기 바란다!

우리 현재 프로젝트에서 우리는 ASP.NET 1.1 애플리케이션으로부터 상당한 량의 텍스트를 오라클 CLOB 필드로 쓸 필요가 있다. 우리는 이제껏 표준 MS System.Data.OracleClient 라이브러리를 (더 작은 량의 데이터를 쓰기위해) 사용해왔고, 그것은 우리에게 아주 유용했다. 나는 오라클 ODP.NET과 같은 더 최신버전의 우수한 팩이 있더라도 다른 라이브러리 팩을 소개하고 싶지 않았다.

예전의 자바 프로젝트에서 나는 CLOB를 쓰고 읽는 작업을 해왔고, 또한 나는 당신이 일반 VARCHAR과 같은 필드를 핸들해야 했다는 것을 안다.

따라서 나는 자리잡고 앉아서 .NET 동적Help과 가능하다면 가능한 모든 인터넷을 뒤지기 시작했고, 그 결과 흥미로운 것이 있었고, 나는 세가지 각각 다른 방법을 발견했다. 두가지는 정말로 단순하고 하나는 그리 단순하지 않다. 희안한 것은 내가 두 옵션은 제대로 작동할 것이라고 생각하지 않고-그러나 내가 테스트 했을 때 제대로 작동했다.
나는 3가지 방법을 여기서 공개할 것이다. 그리고 바라건데 .NET과 Oracle로 지가 머하는가를 아는 누군가는 나를 불꽃으로 격추시킬 수 있길 바란다.(청출어람하길 바란다..)

이것을 테스트 하기위해, 나는 오라클에다가 단순한 테이블을 생성하고, 그 테이블은 2개의 필드로 구성되어있다; ID(INT)와 TEXT(CLOB). 바로 그거다. 나는 노트패드로 생성된 단순 텍스트 파일을 읽을 것이며, 그것은 499KB다.

주: 이것은 테스트코드일 뿐, 당신이 실무에서 하고 싶은 것과는 별개이다. 만약 이코드를 사용하고 싶다면, 적절한 에러나 예외, 핸들링 등을 추가하라.

그래서, OracleDataAdapter를 이용하는 첫번째 방법은 안돌아 갈 것이다.(내가 클래스 라이브러리 문서들을 이해한 기준에서는..). 그러나, 맞긴맞다.

public void writeDataWithDA()

{

           FileInfo fi = new FileInfo("c:/temp/testfile.txt");

           StreamReader sr = new StreamReader(fi.FullName);

           String clob = sr.ReadToEnd();

           sr.Close();

 

           OracleDataAdapter da = new OracleDataAdapter(

               "SELECT ID, TEXT FROM CLOBTEST", ConnectionString);

           DataTable dt = new DataTable();

           // get the schema

           da.FillSchema(dt, SchemaType.Source);

 

           OracleCommandBuilder cb = new OracleCommandBuilder(da);

 

           int id = 2;

 

           // create a row containing the data

           DataRow row = dt.NewRow();

           row["ID"] = id;

           row["TEXT"] = clob;

           dt.Rows.Add(row);

 

           // update the table

           da.Update(dt);

}

두번째 방법은 OracleCommand 를 이용하는 것이며, 이것도 안돌아간다(내 생각엔). 근데 원래는 되는 방법이다.

public void writeDataWithCommand()

{

           FileInfo fi = new FileInfo("c:/temp/testfile.txt");

           StreamReader sr = new StreamReader(fi.FullName);

           String tempBuff = sr.ReadToEnd();

           sr.Close();

           

           using(OracleConnection conn = new OracleConnection(ConnectionString))

           {

                      conn.Open();

                      Console.WriteLine("Connected...") ;

                      String strSQL = 

                          "INSERT INTO CLOBTEST (ID,TEXT) VALUES (1,:TEXT_DATA) ";

 

                      OracleParameter parmData = new OracleParameter();

                      parmData.Direction = ParameterDirection.Input;

                      parmData.OracleType = OracleType.Clob;

                      parmData.ParameterName = "TEXT_DATA";

                      parmData.Value = tempBuff;

 

                      OracleCommand cm = new OracleCommand();

                      cm.Connection = conn;

                      cm.Parameters.Add(parmData);

                      cm.CommandText = strSQL;

                      cm.ExecuteNonQuery();

 

                      conn.Close();

           }

 

           Console.WriteLine("Done!") ;

}

이제 세번째 방법이다. 이것은 .NET 클래스 라이브러리 문서가 기술한 C/BLOB 핸들링 방법이며, 임시 LOB 객체를 오라클에 생성한 다음, insert작업을 하기전에, 그 객체를 쓰므로써 핸들링하는 방법이다. 이것은 역시나 잘돌아간다, 근데 이 방법은 트랜젝션과 다른 부분간에 약간 더 많은 혼란을 겪어야 한다.

public void writeWithTempBlob()

{

           FileInfo fi = new FileInfo("c:/temp/testfile.txt");

           StreamReader sr = new StreamReader(fi.FullName);

           String tempBuff = sr.ReadToEnd();

           sr.Close();

 

           using(OracleConnection conn = new OracleConnection(ConnectionString))

           {

                      conn.Open();

                      Console.WriteLine("Connected...") ;

                      OracleTransaction tx = conn.BeginTransaction();

 

                      OracleCommand tempcmd = conn.CreateCommand();

                      tempcmd.Transaction = tx;

                      tempcmd.CommandText = "declare xx clob; begin dbms_lob.createtemporary(xx, false, 0); :tempclob := xx; end;";

                      tempcmd.Parameters.Add(new OracleParameter("tempclob",

                                 OracleType.Clob)).Direction = ParameterDirection.Output;

                      tempcmd.ExecuteNonQuery();

 

                      //get the temp lob object

                      OracleLob tempLob = (OracleLob)tempcmd.Parameters[0].Value;

 

                      //transform into byte array

                      System.Text.Encoding enc = Encoding.Unicode;

                     //MUST be unicode encoded!

 

                      Byte[] b = enc.GetBytes(tempBuff);

 

                      tempLob.BeginBatch(OracleLobOpenMode.ReadWrite);

                      tempLob.Write(b,0,b.Length);

                      tempLob.EndBatch();

 

                      OracleCommand cmd = conn.CreateCommand();

                      cmd.Transaction = tx;

                      cmd.CommandText = 

                          "INSERT INTO CLOBTEST (ID, TEXT) VALUES (:ID, :TEXT)";

                      cmd.Parameters.Add("ID", 3);

                      cmd.Parameters.Add("TEXT", OracleType.Clob).Value = tempLob;

                      //insert the temp lob

 

                      cmd.ExecuteNonQuery();

 

                      tx.Commit(); 

           }

           Console.WriteLine("Done!") ;

}

임시 CLOB에 write할려면 텍스트는 유니코드여야 한다. 안그러면 당신은 완전 많은 문자들이 쓰여진 것을 경험하게 될 것이니 주의하라.^^

다른 참고자료

FileInfo로 확인할수 없는 해당 파일을 이미 오픈되었는지 확인하는 소스입니다.

구글링 끝에 찾아 내었습니다.

참고하시기 바랍니다.

출처 : http://stackoverflow.com/questions/876473/is-there-a-way-to-check-if-a-file-is-in-use

 

 

protected virtual bool IsFileLocked(FileInfo file)
{
    FileStream stream = null;
    try
    {
        stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
    }
    catch (IOException)
    {
        //the file is unavailable because it is:
        //still being written to
        //or being processed by another thread
        //or does not exist (has already been processed)
        return true;
    }
    finally
    {
    if (stream != null)
        stream.Close();
    }
    //file is not locked
    return false;
}

 

   1:  protected virtual bool IsFileLocked(FileInfo file)
   2:  {
   3:      FileStream stream = null;
   4:      try
   5:      {
   6:          stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
   7:      }
   8:      catch (IOException)
   9:      {
  10:          //the file is unavailable because it is:
  11:          //still being written to
  12:          //or being processed by another thread
  13:          //or does not exist (has already been processed)
  14:          return true;
  15:      }
  16:      finally
  17:      {
  18:      if (stream != null)
  19:          stream.Close();
  20:      }
  21:      //file is not locked
  22:      return false;
  23:  }
 

 

 

 닷넷으로 오픈다이얼로그 박스를 이용한 다중 선택하여 1000개 이상의 파일을 가져오는 경우 XP에서 오류가 발생 되는걸 확인 (windows 7 64bit에서는 오류 없음)

그러나 델파이(정확히는  Lazarus)에서는 오류가 발생되지 않은것으로 보아 닷넷프레임워크나 CLR에서 오류가 발생되는것으로 판단되어 짐

역시 구글링으로 인한 해결 방법을 찾았으나 이것은 오류가 발생시 해당 폴더 전체 파일리스트를 가져오게끔 예외 처리를 하였음

그럼 소스 참고하시기 바랍니다.

 

출처 : http://stackoverflow.com/questions/2607596/how-get-file-names-using-openfiledialog-in-net-1000-file-multiselect

public static string[] GetFiles() 
   
{ 
       
string[] fileNames; 
       
OpenFileDialog openFileDialog1 = new OpenFileDialog(); 
 
        openFileDialog1
.InitialDirectory = UniversalDataImporter.Properties.Settings.Default.openFilePath; 
        openFileDialog1
.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"; 
        openFileDialog1
.FilterIndex = 2; 
        openFileDialog1
.RestoreDirectory = false; 
        openFileDialog1
.Multiselect = true; 
        openFileDialog1
.CheckFileExists = false; 
 
       
try 
       
{ 
           
DialogResult result = openFileDialog1.ShowDialog(); 
           
if (result == DialogResult.OK && openFileDialog1.FileNames.Count() <501 ) 
           
{ 
               
UniversalDataImporter.Properties.Settings.Default.openFilePath = 
                   
Path.GetDirectoryName(openFileDialog1.FileName); 
               
UniversalDataImporter.Properties.Settings.Default.Save(); 
               
return fileNames = openFileDialog1.FileNames; 
           
} 
           
else if (result == DialogResult.Cancel) 
           
{ 
               
return null; 
           
} 
           
else 
           
{ 
               
if (MessageBox.Show("Too many files were Selected. Would you like to import a folder instead?", 
                   
"Too many files...", MessageBoxButtons.YesNo) == DialogResult.Yes) 
               
{ 
                   
return fileNames = GetFilesInFolder(); 
               
} 
               
else 
               
{ 
                   
return null; 
               
} 
           
} 
       
} 
       
catch (Exception ex) 
       
{ 
           
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); 
           
return null; 
       
} 
   
} 
 
   
public static string[] GetFilesInFolder() 
   
{ 
 
       
FileInfo[] fileInfo; 
 
       
string pathName; 
       
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog(); 
 
        folderBrowserDialog
.RootFolder = System.Environment.SpecialFolder.Desktop; 
 
       
DialogResult results = folderBrowserDialog.ShowDialog(); 
 
       
if (results == DialogResult.OK) 
       
{ 
           
try 
           
{ 
                pathName
= folderBrowserDialog.SelectedPath; 
 
               
DirectoryInfo dir = new DirectoryInfo(pathName); 
               
if (dir.Exists) 
               
{ 
 
                    fileInfo
= dir.GetFiles(); 
 
                   
string[] fileNames = new string[fileInfo.Length]; 
 
                   
for (int i = 0; i < fileInfo.Length; i++)//this is shit 
                   
{ 
                        fileNames
[i] = fileInfo[i].FullName; 
                   
} 
 
                   
return fileNames; 
               
} 
               
else 
               
{ 
                   
return null; 
               
} 
 
 
           
} 
           
catch (Exception ex) 
           
{ 
               
MessageBox.Show("Error: Could not read file from disk. Original error: " + ex.Message); 
               
return null; 
           
} 
 
       
} 
       
else if (results == DialogResult.Cancel)  
       
{ 
           
return null; 
       
} 
       
else { return null; } 
   
} 


 

이 글은 스프링노트에서 작성되었습니다.

가장 유명한 VCL, .Net 컴포넌트의 대명가(?)에서 현재 .Net버전의 무료 버전을 배포하고 있네요

종류는 많지는 않습니다 대략 60가지...

정품을 구매하지 않은 사용자가 기본 컴포넌트 대체할려고 하면 좋을 것 같습니다.

메뉴를 통해서 들어가볼려고했지만

어디에 위치한지 몰라 링크 걸어둡니다.

 

https://www.devexpress.com/Products/Free/NetOffer/

 

그럼, 필요하신 분은 잘 사용하시기 바랍니다.

이 글은 스프링노트에서 작성되었습니다.

 

이 글 작성 당시에는 무료 컴포넌트가 제공 되었으나, 지금 현재는 정품 트라이얼 버전 링크로 수정 되었습니다.

 

C#에서 현재 경로를 알아내는 방법은 여러가지가 있다.

1. System.Environment.CurrentDirectory

가장 쉽게 현재 실행 경로를 알아낼 수 있는 방법이다. 하지만 이 방법은 Register에 등록된 프로그램으로 실행되면 다른 값을 출력한다. 이때는 3번 Application.StartupPath를 이용해야 한다.

* 루트일 경우에는 ‘\’ 반환, 그 외의 경우에는 폴더명까지만 반환한다.

  • C:\
  • C:\TestFolder\MyApp


2. System.IO.Directory.GetCurrentDirectory()


1번과 동일하다.


3. Application.StartupPath

위의 Register에 등록되었을 때도 정상적으로 자신의 시작 경로를 반환한다. 하지만 이는 Window Forms를 사용할 때만 Application 클래스를 사용할 수 있기 때문에 Console 기반 혹은, 클래스 라이브러리 기반에서는 사용이 불가능하다.

Tip. Application.ExecutablePath
현재 실행된 어플리케이션의 실행 파일의 위치이다. C:\Test\App.exe 와 같이 출력된다. 이 정보는 현재 경로가 아니기 때문에 변경되지 않는다.

 

 출처 : http://pureholic.net/2010/04/how-to-kwow-startpath-in-csharp/

이 글은 스프링노트에서 작성되었습니다.

Form Style - fsStayOnTop 효과

 SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE)

<-> SetWindowPos(Handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);

 

출처 :  http://www.delmadang.com/community/bbs_view.asp?bbsNo=17&bbsCat=41&indx=405581&keyword1=fsStayOnTop&keyword2=

이 글은 스프링노트에서 작성되었습니다.

+ Recent posts