2012년 9월 17일 월요일

FluorineFX가 정상적으로 구동되지 않는 경우 참고...

  • 환경 : FluorineFX, Flash Builder 4.5, IIS 7.5
  • 개요 : FluorineFX를 통해서 Server Module을 구성하고 Flash Builder를 통해서 Client Module을 구성하여 IIS 7.5에 Porting을 하면 "NetConnection.Connect.Failed" 오류가 발생하고 Fluorine FX의 로그에서는 "Failed to locate the requested Type" 오류 로그가 발생하였다.
  • 증상
    1. Video Recording 어플에서 정상적으로 FluorineFX가 기동되지 않았다.
    2. Flex의 디버그 상에서는 NetConnection.Connect.Failed 오류가 발생함.
    3. FluorineFX 로그 상에서는 Failed to locate the requested Type 로그가 표시됨.
  • 원인 분석
    1. IIS에 포팅된 웹어플리케이션에서 WEB-INF/flex/services-config.xml 파일을 삭제한 것이 원인이었다. 해당 파일은 Flex에서 어플을 만들 때,  Channel의 정보를 알려주기 위한 목적만 있는 것으로 이해를 했다. Flex 어플은 당연히 RTMP로 통신을 하기 때문에 Channel 정보가 불필요할 것으로 판단을 하고 삭제를 했던 것인데, FluorineFX 모듈에서도 해당 Channel 정보를 이용해서 기동하는  것 같다. 따라서 해당 파일을 삭제하니 FluorineFX가 정상적으로 기동되지 않았던 것이다.


참고로 Services-config.xml 파일의 내용은 다음과 같다.

<?xml version="1.0" encoding="utf-8" ?>
<services-config>
  <channels>
    <channel-definition id="my-rtmp" class="mx.messaging.channels.RTMPChannel">
      <endpoint uri="rtmp://{server.name}:1935" class="flex.messaging.endpoints.RTMPEndpoint"/>
    </channel-definition>
  </channels>
</services-config>

2012년 9월 12일 수요일

Error 1001. 설치를 초기화하는 동안 예외가 발생했습니다. System.BadImageFormatException

증상 :
Install Program에서 아래의 오류가 발생하고 설치가 실패


오류 내용 : 
Error 1001. 설치를 초기화하는 동안 예외가 발생했습니다.
System.BadImageFormatException : 파일이나 어셈블리 file:///C:\...\RIALab.Streaming.EncodingService.exe 또는 여기에 종속되어 있는 파일이나 어셈블리 중 하나를 로드할 수 없습니다. 현재 로드된 런타임보다 최신 런타임으로 어셈블리를 빌드했으므로 어셈블리를 로드할 수 없습니다.


원인 :
원래 설치하고자 하는 시스템은 .Net Framework 3.5를 기준으로 만들어졌고 Setup Project 또한 .Net Framework 3.5로 만들어졌었다.
이 프로젝트를 .Net Framework 4.0으로 Migration을 하고 설치 파일을 만들었으나 위의 오류가 발생하였다.

오류가 발생했던 원인은 단순했다.

Setup Project를 마우스 우클릭하여 View > Launch Conditions을 클릭하면 해당 화면이 표시되는데 "Launch conditions"라는 폴더 하부에 ".Net Framework"라는 항목이 있는 것을 볼 수 있다.
해당 항목을 클릭해서 속성을 보면 "Version" 값이 "3.5.30729"로 잡혀 있는 것을 확인할 수 있다.

즉, .Net 4.0으로 Migration을 하더라도 기존의 .Net 3.5 버젼 값은 변경되지 않아서 발생했던 문제다.


처리 방법 :
Version 값을 ".Net Framework 4.0"으로 변경/선택한다.

2012년 9월 11일 화요일

ffmpeg option에 대한 예제 및 설명

출처 : 아싸 좋구나 님의 블로그 (http://dicer.tistory.com/179)

아래의 내용은 계속해서 보강/수정할 예정임.

[내용]

제가 예전에 올려드린 배치파일 내에서 ffmpeg.exe 옵션에 대한 도움말입니다

길이 길어지는걸 방지하기 위해 따로 옮겼습니다

구형 배치파일을 기준으로 작성되었습니다만 신형배치파일과 대동소이합니다

배치파일
@echo off

for %%i in (%1, %2, %3, %4, %5, %6, %7, %8, %9) do
(
 ffmpeg.exe
 -y -i "%%~i" -threads 0 -vcodec libx264 -preset slow -crf 26 -sws_flags lanczos
 -vf "yadif=1:-1, crop=in_w-2*16:in_h-2*16, scale=1280:720, setsar=1:1"
 -r 60000/1001 -acodec aac -strict experimental -ab 192k -ac 2 -ar 44100
 "%%~ni.720p_60fps.x264_crf26.aac_192k.HQ.mp4"
)

//-----------------
// -threads 0
//-----------------
몇 스레드로 인코딩할지 결정
0으로 설정하면 자동선택
자신의 코어수로 설정
하이퍼스레딩을 쓴다면 코어수*2

그냥 0으로 쓰는게 최고
아니면 그냥 이옵션을 생략해두됨 그러면 기본값으로 0이 적용됨

//----------------------------------
// -vcodec libx264 -preset medium
//----------------------------------
x264를 이용해서 medium 프리셋 옵션으로 인코딩을 한다는 뜻
작년부터 x264에서 자체적으로 프리셋(일반적인 용도로 최적화된 옵션세팅)을 넣어서 배포하기 시작했는데
x264를 사용하는 많은 국산외산 인코더들은 이기능을 잘 활용하지않고
인코딩 속도를 위해 엉망인 옵션(me랑 subme를 대폭 낮추면 속도업 화질다운)을 기본설정으로 사용하고있습니다

medium 전단계인 fast만해도 충분히 좋은 화질을 얻을수 있구요
컴터 cpu가 빠방하다면 medium대신 slow나 veryslow를 넣어주시면됩니다

//----------------------------------------------------------------------
// 만약 baseline profile만 재생가능한 휴대기기용으로 인코딩을 하시려면
//----------------------------------------------------------------------
-x264opts cabac=0:bframes=0:ref=1:8x8dct=0:weightp=0
이걸 추가해주시면 baseline profile로 인코딩을 해줍니다
소형기기에서 재생하실테니 해상도도 줄여주시고
60프레임 bob디인터레이싱도 필요없으니 중간에 yadif=1,-1도 yadif=0,-1로 바꿔주시고
60000/1001 이것도 30000/1001로 수정해주시면 됩니다
-crf 26도 abr모드로 바꿔주세요 -b 1000k 이런식으로 

//---------------------------------------------------------
// 아이패드나 휴대기기용으로 main profile로 인코딩하시려면
//---------------------------------------------------------
-x264opts 8x8dct=0:weightp=0:level=31
이걸 넣어주세요
main은 baseline보다 cpu에 많이 부담이 가는데 high보다는 좀 적게 갑니다

//----------
// -crf 26
//----------
crf모드라고 화질기준 인코딩입니다 2pass보다 낫습니다
2pass는 주어진 비트레이트 내에서 최대효율을 추구한다면
crf는 비트레이트 제한이 없습니다
그래서 이미 손실이 일어난 hdtv영상이 원본인경우 오버슈팅이 발생하기도하는데
다른옵션을 통해 비트레이트 낭비를 막아줄수 있습니다
자세한거는 따로 물어보시고 일반인들은 요부분 패스하셔두됩니다
 
더 좋은 화질을 추구하신다면 -crf 25로 숫자를 줄여주시면 됩니다
근데 26만해도 충분하실겁니다 27 28정도로 높여도 hdtv소스가 구린경우는 별로 화질저하가 잘 느껴지지 않습니다 대신 용량은 팍팍 줄어들죠
abr모드로 인코딩을 하고싶으시면 -crf 26을 지우시고 -b 3000k 와같이 용량을 직접 적어주시면됩니다

//-----------------------
// -sws_flags lanczos
//-----------------------
lanczos 알고리즘으로 리사이즈를 합니다 근데 libavfilter로 리사이즈를 처리하는거라서 적용되는건지 확실치 않네요

//-------------------------------------------------------------------------
// -vf "yadif=1:-1, crop=in_w-2*16:in_h-2*16, scale=1280:720, setsar=1:1"
//-------------------------------------------------------------------------
큰따옴표 전체가 ffmpeg에 인코딩들어가기 전에 libavfilter로 처리해주는 부분입니다

//--------------
// yadif=1:-1,
//--------------
60프레임 bob 디인터레이싱 옵션입니다 움직임이 많은 영상에서는 필수죠
예능같은거 인코딩하실때는 굳이 60프레임으로 하실 필요없습니다
=1:-1 부분을 =0-:1 로 바꿔주시면
30프레임으로 디인터레이싱되서 인코딩 됩니다
더불어 뒤에 나오는 60000/1001 부분도 30000/1001로 수정해주셔야겠죠
그리고 일부 드라마나 hd로 방영되는 영화들은 이방법을 쓰면 안됩니다
그넘들은 원본이 24프레임이라서 텔레시네를 통해 60i로 변환되서 방송되는데
이들을 원래대로 돌리기위해서는 디인터레이싱이 아니라 역텔레시네(ivtc)를 해줘야해요
mplayer필터기능을 통해 ivtc를 해주는 필터(명령어 mp=ivtc)를 사용할수 있는데 현재는 제대로 작동이 안됩니다
아 그리고 소스자체가 프로그레시브인 블루레이나 캠코더영상은 이부분을 완전 빼주세요

//----------------------------
// crop=in_w-2*16:in_h-2*16
//----------------------------
이건 좌우 위아래서 16픽셀씩 잘라낸다는 뜻입니다
hdtv는 모서리에 블랙바나 잡신호가 끼고 방송국mpeg2인코더 특성상 1088로 출력되기때문에 크롭이 필수입니다
기호에 따라 바꿔주시면 됩니다

//-----------------------------
// scale=1280:720, setsar=1:1
//-----------------------------
scale은 화면크기구요 setsar은 그냥 냅두세요
setsar부분을 건드려주시면 아나몰픽 인코딩이 가능합니다

//------------------
// -r 60000/1001
//------------------
libavfilter에서 60프레임으로 넘겨주기 때문에 60프레임이라고 따로 지정해줘야합니다
30프레임이면 30000/1001 이라고
60대신 60000/1001을 쓰는 이유는 방송규격이 그래서

//------------------------------
// -acodec libmp3lame -ab 160k
//------------------------------
오디오코덱을 mp3로 오디오 비트레이트를 160k로 지정해주는 구문입니다
hdtv방송 출력(보통 192k ac3 일본방송은 aac)을 그대로 넣고 싶다면
이부분 전체를 -acodec copy로 바꿔주시면됩니다
그러면 인코딩없이 원본이 그대로 들어갑니다
aac로 인코딩 하겠다는 분들은
-acodec libmp3lame대신에 -acodec aac -strict experimental 을 넣어주시면됩니다
원래는 외부소스인 faac를 썼었는데 최근에 ffmpeg이랑 결별을 했구요
이제 ffmpeg은 자체적인 aac인코더를 씁니다
근데 faac나 ffmpeg aac나 성능이 nero에서 배포하는 aac인코더보다 못해요 그래서 experimental 옵션을 넣어줘야합니다
예전에는 둘다 완전 쓰레기였는데 요즘에는 그래도 인코더 구실을 합니다
아 그리고 기존 메구이를 이용한 방법에서는 일본방송 ts를 인코딩할때 일본방송은 aac를 써서 에러가 났었는데
ffmpeg을 이용한 방법에서는 에러없이 잘됩니다

//-------------------------------------------------
// "%%~ni.720p_60fps.x264_crf26.aac_192k.HQ.mp4"
//-------------------------------------------------
컨테이너를 mp4로 지정합니다 mkv를 쓰셔두되구요
근데 왠만하면 avi를 쓰지맙시다 h264코덱이랑 궁합이 안좋아요
특정폴더에 인코딩한걸 출력하길 원하시면
"c:\원하는폴더\%%~ni.720p_60fps.x264_crf26.aac_192k.HQ.mp4"
이런식으로 바꿔주면 됩니다
.720p_60fps.x264_crf26.aac_192k.HQ
요부분도 원하시는대로 바꾸셔두됨


=================================================================================
 내용추가

start /high /b /wait ffmpeg.exe -y -i "%~1" -threads 0 -vcodec libx264 -preset slow -crf 26 -sws_flags lanczos -vf "yadif=1:-1, crop=in_w-2*16:in_h-2*16, scale=1280:720, setsar=1:1" -r 60000/1001 -acodec libmp3lame -ab 192k -ac 2 -ar 44100 "%~d1%~p1%~n1.720p_60fps.x264_crf26.mp3_192k.HQ.mp4"

신형배치파일 구문에서

start /high /b /wait
 시피유 활용 우선순위를 높음으로 ffmpeg.exe를 작동시킵니다

다른작업시 약간 버벅거릴수 있습니다 원치 않으시면 이부분을 빼주세요


"%~d1%~p1%~n1.720p_60fps.x264_crf26.mp3_192k.HQ.mp4"
 폴더경로를 다 지정해주게 바꿨습니다

특정폴더에 저장하고 싶으시면 %~d1%~p1 요부분을 바꿔주세요 c:/동영상/ 이렇게 말이죠

2012년 9월 3일 월요일

"WebServiceHandlerFactory-Integrated 처리기의 모듈 목록에 잘못된 모듈 ManagedPipelineHandler가 있습니다."오류 발생시 처리 방법

증상 : IIS 7.x에서  아래와 같은 HTTP 오류가 발생한다.
오류 내용 : 
HTTP 오류 500.21 - Internal Server Error
WebServiceHandlerFactory-Integrated 처리기의 모듈 목록에 잘못된 모듈 ManagedPipelineHandler가 있습니다.

원인 : .Net Framework 4.0이 제대로 설정이 설치(설정)가 되지 않아서 발생된 문제임.

처리 방법 :  %windir%\Microsoft.NET\Framework\v4.0.21006\aspnet_regiis.exe -i
(64bit machie : C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe -i)
Framework 버젼에 따라 경로명이 틀려질 수 있으므로 유의할 것.

2012년 8월 28일 화요일

FluorineFX의 RTMP (Video Recording)이 정상적으로 작동하지 않는 경우

  • 환경 : FluorineFX, Flash Builder 4.5, IIS 7.5
  • 개요 : FluorineFX을 이용하여 Video Recording이 가능한 모듈을 개발하였으나 
     NetConnection.Connect.Failed 오류가 발생함.
  • 증상
    1. FluorineFX에서 제공되는 Sample(설치폴더\Samples\Flex\Rtm\VideoChat) 코드를 Visual Studio 2010에서 ASP.NET Development Server를 통해서 실행하면- 즉 Debug을 실행하면 - 정상적으로 FluorineFX의 RTMP에 접속됨.
    2. 위의 코드를 기반으로 해서 만들어진 Video Recoring 모듈을 IIS 7.5 포팅을
      하고 기동을 하면 NetConnection.Connect.Failed 오류가 발생함.

  • 원인 분석
    1. IIS 7.5의 응용프로그램 풀에서 유휴시간 때문인 것으로 분석이 됨.
      (정확한 분석은 아니다. 이렇게 처리를 하니까 문제가 발생하지 않아서 미루어 짐작하는 것이다. IIS7.0 에서는 문제가 없었다)
      유휴 시간으로 설정된 시간이 초과되면 관련 프로세스가 중지되는 것으로 보인다.
  • 처리 방안
    1. "응용프로그램 풀 >> 프로세스 모델 >> 유휴시간 제한"을 0으로 설정하여 제약을 두지 않는다.
  • RTMP 관련 참고 사항
    1. rtmp://localhost/VideoRecording => 웹 루트/apps/VideoRecording 폴더와 맵핑되고
      웹 루트/apps/VideoRecording/streams 폴더 밑에 동영상이 저장된다.
    2. VideoRecording이 사용되는 서버 모듈에 대한 정의는 웹 루트/apps/app.config에 정의되어 있다.

      아래는 video recording과 관련된 app.config이다.

      <?xml version="1.0" encoding="utf-8"?>
      <configuration>
        <!-- Application object. Specify a fully qualified type name for your handler -->
        <application-handler type="RIALab.Framework.Streaming.VideoRecordingApplication"/>
        <!--streamFilenameGenerator type="RIALab.Framework.Streaming.FileNameGen"/-->
      </configuration>
    3. WEB-INF/flex/services-config.xml 을 flex에 지정할 필요가 없다.
      RTMP 통신은 rtmp://localhost/VideoRecording 와 통신을 직접하기 때문이다.
    4. Web.Config에 (.Net 4.0 기준) RTMP - fluorineFx 관련 설정
      <?xml version="1.0" encoding="UTF-8"?>
      <configuration>
        <configSections>
          <sectionGroup name="fluorinefx">
            <section name="settings" type="FluorineFx.Configuration.XmlConfigurator, FluorineFx" requirePermission="false" />
          </sectionGroup>
          <!--log4net setup : start-->
          <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
          <!--log4net setup : end-->
          <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
          <section name="securityCryptographyConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration.CryptographySettings, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </configSections>
        <!--log4net setup : start-->
        <log4net>
          <root>
            <level value="ALL" />
            <appender-ref ref="RollingFileAppender" />
          </root>
          <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
            <param name="file" value="./log/pasteleditor" />
            <appendToFile value="true" />
            <rollingStyle value="Date" />
            <lockingModel type="log4net.Appender.FileAppender+MinimalLock" />
            <datePattern value="_yyyyMMdd&quot;.log&quot;" />
            <layout type="log4net.Layout.PatternLayout">
              <conversionPattern value="%message%newline" />
            </layout>
          </appender>
        </log4net>
        <!--log4net setup : end-->
        <appSettings>
          <add key="BACKGROUND_IMG_VPATH" value="/uploadData/backgroundImage" />
          <!--배경이미지 가상경로-->
          <add key="BACKGROUND_MUSIC_VPATH" value="/uploadData/music" />
          <!--음악파일경로(mp3)-->
          <add key="UPLOAD_IMAGE_VPATH" value="/uploadData/image/" />
          <add key="UPLOAD_CLIPART_VPATH" value="/uploadData/clipart_thumb/" />
          <add key="UPLOAD_DOCUMENT_VPATH" value="/uploadData/document/" />
          <add key="UPLOAD_MOVIE_VPATH" value="/uploadData/movie/" />
          <add key="UPLOAD_FRAME_VPATH" value="/uploadData/frame/" />
          <add key="UPLOAD_DRAW_VPATH" value="/uploadData/draw/" />
          <add key="UPLOAD_SHAPE_VPATH" value="/uploadData/shape/" />
          <add key="UPLOAD_CHART_VPATH" value="/uploadData/chart/" />
          <add key="UPLOAD_TEXT_VPATH" value="/uploadData/text/" />
          <add key="UPLOAD_LINK_MOVIE_VPATH" value="/uploadData/linkmovie/" />
          <add key="UPLOAD_LINK_VIEWER_VPATH" value="/uploadData/viewer/" />
          <add key="UPLOAD_BACK_THUMB_VPATH" value="/uploadData/backgroundImage_thumb/" />
          <add key="UPLOAD_VOICE_VPATH" value="/uploadData/voice/" />
          <add key="UPLOAD_EQUATION_VPATH" value="/uploadData/equation/" />
          <add key="UPLOAD_DOCUIMG_VPATH" value="/uploadData/docuimage/" />
          <add key="UPLOAD_TEMPLATE_VPATH" value="/uploadData/template/" />
          <add key="CMD_ENCODER_VPATH" value="/encoderData/" />
          <add key="CMD_TEX_VPATH" value="/texData/" />
          <add key="CMD_FLEX_VPATH" value="/flexData/" />
          <add key="CMD_SWF_VPATH" value="/swfData/" />
          <add key="TEMPDATA_VPATH" value="/tempData/" />
          <add key="META_XML_VPATH" value="/mxmlData/metaXML/" />
          <add key="USER_MXML_VPATH" value="/mxmlData/userMXML/" />
          <add key="COMPILED_MXML_VPATH" value="/mxmlData/compiledMXML/" />
          <add key="SMALLSWF_VPATH" value="/mxmlData/smallSWF/" />
          <add key="MAKEIMAGE_VPATH" value="/mxmlData/makeimage/" />
          <add key="MXML_THUMBLAIL_VPATH" value="/mxmlData/thumbnail/" />
          <add key="MXML_BACKGROUNDIMAGE_VPATH" value="/mxmlData/backgroundimage/" />
          <add key="MXML_TEMPLATEDATA_VPATH" value="/mxmlData/templateData/" />
          <add key="VOICEDATA_STREAMS_VPATH" value="/voicedata/streams/" />
          <add key="STREAMDATA_VPATH" value="/streamData/vod/media/" />
          <add key="BACKUPDATA_VPATH" value="/backup/" />
          <add key="HOST_NAME" value="localhost" />
          <add key="UPLOAD_DATA_VPATH" value="/uploadData/" />
          <add key="ADMIN_DATA_VPATH" value="/pastelData/adminData/" />
          <!--단위 : MB-->
          <add key="IMAGE_MAX_SIZE" value="1"/>
          <add key="MOVIE_MAX_SIZE" value="300"/>
          <add key="DOCUMENT_MAX_SIZE" value="100"/>
          <add key="ETC_MAX_SIZE" value="1"/>
          <add key="MP3_MAX_SIZE" value="10"/>
          <!--add key="OPENOFFICE_PATH" value="D:\temp\OpenOfficePortable\OpenOfficePortable.exe"/-->
          <add key="EBS_THUMBLAIL_VPATH" value="/thumbnailData" />
          <add key="OPENOFFICE_PAGE_LIMIT" value="true" />
          <add key="OPENOFFICE_PAGE_LIMIT_COUNT" value="10" />
        </appSettings>
        <fluorinefx>
          <settings>
            <!-- <application-handler>FluorineFx.Messaging.Adapter.ApplicationAdapter</application-handler> -->
            <rtmpServer>
              <threadpool minWorkerThreads="0" maxWorkerThreads="25" idleTimeout="60000" />
              <!-- Ping clients every "pingInterval" ms. Set to 0 to disable ghost detection code. -->
              <!-- Disconnect client after "maxInactivity" ms of not responding. -->
              <!-- Max. time in milliseconds to wait for a valid handshake. -->
              <rtmpConnection pingInterval="0" maxInactivity="60000" maxHandshakeTimeout="0" />
              <rtmptConnection pingInterval="5000" maxInactivity="60000" maxHandshakeTimeout="5000" />
              <rtmpTransport receiveBufferSize="4096" sendBufferSize="4096" tcpNoDelay="true" />
            </rtmpServer>
          </settings>
        </fluorinefx>
        <connectionStrings>
          <!--add name="KMDB" connectionString="provider=MSDAORA;Data Source=xxxxxxx;User ID=xxxxx;Password=xxxxxx;" providerName="System.Data.OleDb"/-->
          <add name="PastelEditorConnectionString" connectionString="data source=C:\6000.IIS_Data\Kings_2012\dataRoot\xxxxxxxx.db3" providerName="System.Data.SQLite" />
          <!--add name="PastelEditorConnectionString" connectionString="data source=(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=xxx.xxx.xxx.xxx)(PORT=1545))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=DBPEDRB)));user id=xxxxxx;password=xxxxxxx;pooling=false" providerName="System.Data.OracleClient" /-->
          <!--add name="PastelEditorEntities"          connectionString="metadata=res://*/DataSet.Model1.csdl|res://*/DataSet.Model1.ssdl|res://*/DataSet.Model1.msl;provider=System.Data.SQLite;provider connection string='data source=&quot;F:\2000.Project Data\2300.Year_Section\FY2010\201008.xxxxx\02.개발\04.Database\xxxxx.db3&quot;'" providerName="System.Data.EntityClient"/-->
        </connectionStrings>
        <securityCryptographyConfiguration>
          <hashProviders>
            <add algorithmType="System.Security.Cryptography.MD5CryptoServiceProvider, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" saltEnabled="false" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="CL_MD5" />
            <add algorithmType="System.Security.Cryptography.SHA1Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" saltEnabled="false" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="CL_SHA1" />
            <add algorithmType="System.Security.Cryptography.SHA256Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" saltEnabled="false" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="CL_SHA256" />
            <add algorithmType="System.Security.Cryptography.SHA384Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" saltEnabled="false" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="CL_SHA384" />
            <add algorithmType="System.Security.Cryptography.SHA512Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" saltEnabled="false" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="CL_SHA512" />
          </hashProviders>
          <symmetricCryptoProviders>
            <add algorithmType="System.Security.Cryptography.RijndaelManaged, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" protectedKeyFilename="C:\ubion\EncKey.key" protectedKeyProtectionScope="LocalMachine" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.SymmetricAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="CL_Rijndael" />
          </symmetricCryptoProviders>
        </securityCryptographyConfiguration>
        <system.web>
          <!--
                  컴파일된 페이지에 디버깅 기호를 삽입하려면
                  compilation debug="true"로 설정하십시오. 이렇게 하면
                  성능에 영향을 주므로 개발하는 동안에만 이 값을
                  true로 설정하십시오.
              -->
          <compilation debug="true" targetFramework="4.0">
          </compilation>
          <!--
                  <authentication> 섹션에서는 ASP.NET에서 사용되는
                  보안 인증 모드의 구성을 설정하여 들어오는
                  사용자를 식별할 수 있습니다.
              -->
          <authentication mode="Windows" />
          <!--
                  <customErrors> 섹션에서는 요청을 실행하는 동안
                  처리되지 않은 오류가 발생하는 경우 수행할 작업을
                  구성할 수 있습니다. 특히 이 섹션에서는
                  개발자가 오류 스택 추적 대신 html 오류 페이지가 표시되도록
                  구성할 수 있습니다.
    5.         <customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
                  <error statusCode="403" redirect="NoAccess.htm"/>
                  <error statusCode="404" redirect="FileNotFound.htm"/>
              </customErrors>
              -->
          <httpRuntime executionTimeout="90" maxRequestLength="2097000" useFullyQualifiedRedirectUrl="false" minFreeThreads="8" minLocalRequestFreeThreads="4" appRequestQueueLimit="100" />
          <httpModules>
            <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx" />
          </httpModules>
          <pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID" />
        </system.web>
        <!--
              IIS(Internet Information Services) 7.0에서 ASP.NET AJAX를 실행하려면
              system.webServer 섹션이 필요합니다. 이전 버전의 IIS에서는 필요하지 않습니다.
          -->
        <system.webServer>
          <security>
            <requestFiltering>
              <requestLimits maxAllowedContentLength="2000000000" />
            </requestFiltering>
          </security>
          <modules>
            <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx" preCondition="managedHandler" />
          </modules>
          <handlers>
            <add name="*.vbhtml_*" path="*.vbhtml" verb="*" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.vbhtm_*" path="*.vbhtm" verb="*" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.cshtml_*" path="*.cshtml" verb="*" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.cshtm_*" path="*.cshtm" verb="*" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.aspq_*" path="*.aspq" verb="*" type="System.Web.HttpForbiddenHandler" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.xamlx_*" path="*.xamlx" verb="*" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.xoml_*" path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.svc_*" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.soap_*" path="*.soap" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.rem_*" path="*.rem" verb="*" type="System.Runtime.Remoting.Channels.Http.HttpRemotingHandlerFactory, System.Runtime.Remoting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*.asmx_*" path="*.asmx" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="ScriptResource.axd_GET,HEAD" path="ScriptResource.axd" verb="GET,HEAD" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="*_AppService.axd_*" path="*_AppService.axd" verb="*" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv2.0" />
            <add name="eurl.axd_*" path="eurl.axd" verb="*" type="System.Web.HttpNotFoundHandler" preCondition="integratedMode,runtimeVersionv2.0" />
          </handlers>
          <validation validateIntegratedModeConfiguration="false" />
        </system.webServer>
        <startup>
          <supportedRuntime version="v2.0.50727" />
        </startup>
      </configuration>

    2012년 8월 21일 화요일

    iTextSharp에서 한글-CJK 사용하기

    iTextSharp을 이용해서 한글을 삽입하는 방법

    1. dll로 감싸여져 있는 iTextSharp에서 제공하는 폰트를 이용하는 방법

      Embedding 방식이 아닌 것으로 추정되며 생성된 PDF의 파일 크기가 작은 특징을 가지고 있다.

      iTextSharp에서 제공하는 Font 이름은
      HYGoThic-Medium
      HYSMyeongJo-Medium
      HYSMyeongJoStd-Medium
      이다.

      글자의 쓰기 방향을 결정하는 CMap은
      UniKS-UCS2-H
      UniKS-UCS2-V
      이 있다.
      (H로 끝나는 것은 가로 쓰기, V는 세로쓰기)

      (사용방식)
      BaseFont.AddToResourceSearch("iTextAsian.dll");
      BaseFont bf = BaseFont.CreateFont("HYSMyeongJoStd-Medium", "UniKS-UCS2-H", BaseFont.NOT_EMBEDDED);
      Font font = new Font(bf, 12, Font.BOLD|Font.UNDERLINE, BaseColor.RED);
      위와 같이 사용을 하면 된다. 그리고 iTextAsian.dll 파일은 debug 폴더(또는 만들어진 프로그램이 설치되는 폴더)에 위치하면 된다.
    2. PC에 존재하는 폰트를 불러 들이는 방법
      Embedding 방식으로 추정이 된다. 동일한 내용에 대해서 1번에 의해 생성된 파일보다  4배 정도의 사이즈 차가 발생한다.

      (사용방식)
      BaseFont bf = BaseFont.CreateFont("malgun.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);OrBaseFont bf = BaseFont.CreateFont("HMFMMUEX.TTC,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
      Font font = new Font(bf, 12, Font.BOLD|Font.UNDERLINE, BaseColor.RED);
      의 방식으로 사용한다.
      PC에 존재하는 폰트를 사용하기 위해서는 다음의 폰트 유형 중에 하나이어야 한다.

      * Type1 font files (.afm, .pfm, .pfb)로서 잘 알지는 못하지만 Adobe에서 만들어진 폰트로 알고 있다.
      * TrueType font files - .ttf (Adobe의 Type1 폰트와 경쟁하기 위해서 Apple에서 개발된 폰트)
      * OpenType font files - .otf, .ttf, .tttc (Unicode에 근간한 cross-platform 폰트 파일 포맷)

      ttf 형식의 폰트는 폰트명을 "malgun.ttf"로 지정하지만 ttc 형식의 폰트는 폰트명을"HMFMMUEX.TTC,0"와 같이 ",0"이 추가된다. 이것은 ttc는 ttf의 collection을 위해서 사용되는 것이기 때문에 ttf 중에서 첫번째 ttf를 사용하도록 하기 위한 것이다.

      폰트명을 지정할 때, 해당 폰트가 debug 폴더(또는 만들어진 프로그램이 설치되는 폴더)에 위치하는 경우에는 경로없이 폰트 파일 이름을 기재하면 되지만 직접 경로를 기재해도 된다. 예를 들어서, C:/windows/fonts/malgun.ttf와 같이 기재할 수 있다.

      여기서 주의할 것은 한글이 제대로 표시되려면 한글전용폰트를 사용해야 한다는 것이다. courier, arial과 같은 폰트도 윈도우에서는 지원되지만 iTextSharp에서는 해당 폰트를 사용하면 한글이 표시 되지 않는다. (이 부분은 내가 잘못 알고 있는 부분일지도 모른다.)adobe의 폰트인 afm 파일도 마찬가지로 Courier.afm등의 파일을 iTextSharp을 통해서
      불러들이면 한글이 표시되지 않는 현상이 발생한다.


      (대략적인 사용방법)
      using iTextSharp.text;
      using iTextSharp.text.pdf;

      ......

      //iTextSharp의 폰트를 사용할 경우
      BaseFont.AddToResourceSearch("iTextAsian.dll");
      BaseFont bf = BaseFont.CreateFont("HYSMyeongJoStd-Medium", "UniKS-UCS2-H", BaseFont.NOT_EMBEDDED);

      //폰트 파일을 사용하는 경우 - ttf
      BaseFont bf = BaseFont.CreateFont("malgun.ttf", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
      //폰트 파일을 사용하는 경우 - ttc
      BaseFont bf = BaseFont.CreateFont("HMFMMUEX.TTC,0", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

      Font font = new Font(bf, 12, Font.BOLD|Font.UNDERLINE, BaseColor.RED);
                       
      writer.CompressionLevel = 0;
      UTF8Encoding utf8 = new UTF8Encoding();
      Byte[] utf8String = utf8.GetBytes("Hello World 안녕하세요");
      Phrase hello = new Phrase();
      Chunk chunk = new Chunk(utf8.GetString(utf8String), font);

      hello.Add(chunk);
      PdfContentByte canvas = writer.DirectContentUnder;
      ColumnText.ShowTextAligned(canvas, Element.ALIGN_LEFT, hello, 100, 100, 0);

      위의 코드에서 PDFWrite와 Document에 대한 참조는 생략되었으므로 주의하라.

    2012년 8월 16일 목요일

    Visual Studio 2010 - Windows Service 구성 및 배포 파일 구성

    Windows Service를 구성하고 배포 파일을 만들 때 마다 매번 시행착오를 거치는 관계로 간단하게 내용을 정리한다.

    1. Windows Service 구성 방식은 아래의 URL을 참고하여 구성을 한다.

    http://msdn.microsoft.com/ko-kr/library/zt39148a.aspx

    해당 Service에 들어가는 코드는 기존에 만들어진 서비스를 참고해서 코드를 추가한다.
    위의 URL에서 참고하고자 하는 내용은 ProjectInstaller, ServiceInstaller1, ServiceProcessInstaller1의 구성 방법에 대한 내용 들이다.

    2. 1을 통해서 Windows Service가 구성이 되면 이를 배포하는 프로젝트를 만들어서 Setup.exe를 실행하면 해당 Windows Service가 Local System에 설치가 되고 Service에 자동으로 등록이 되도록 하는 방법은 다음과 같다.

    기존에 만들어진 배포프로젝트 대로 구성을 하면 되는데 항상 아래의 내용을 빼 먹는 관계로
    Service에 만들어진 서비스 프로그램이 등록되지 않았다.



    위의 그림에서 배포프로젝트를 우측 마우스로 클릭해서 "View->Custom Action"을 선택한다.
    선택해서 아래의 그림이 표시되면 "Install", "Commit", "Rollback", "Uninstall"에 1에서 구성한 Window Service 프로그램에 대한 Primary Output을 지정하여야만 설치시에 자동으로 만들어진 Service가 Service 목록에 등록이 된다.



    MS Office Interop를 이용해서 개발한 Windows Service가 정상적으로 작동하지 않을 때..

    • 환경 : Microsoft Office 2010, Visual Studio 2010, Windows 7, Windows 2008 Server
    • 개요 : MS Office 2010 Interop (14version)을 이용해서 Powerpoint, Word, Excel 파일을
      PDF로 변환하는 Windows Service Program을 개발하여 포팅하였으나 Program이 정상적으로 구동되지 않았다.
    • 증상
      1. 변환 프로그램을 개발하는 Visual Studio 2010에서 Test Program인 Console Application으로 작동을 시켜보면 정상적으로 Program이 기동되었다.
      2. 1의 테스트를 확인하고 Windows Service로 배포하는 프로젝트를 생성하여 정상적으로 Windows Service에등록이 된 것을 확인하고, 구동을 시켜보니 정상적으로 작동하지 않았다.
      3. Program에서 작동하는 로그을 확인해 보니,
        "개체 참조가 개체의 인스턴스로 설정되지 않았습니다."라는 메세지와
        "'C:\temp\document\7.xlsx' 파일을 사용할 수 없습니다. 원인은 다음과 같습니다
        해당 파일 이름이나 경로가 없습니다. 다른 프로그램에서 파일을 사용하고 있습니다.저장하려고 하는 통합 문서 이름이 현재 열려 있는 통합 문서의 이름과 같습니다."라는 메세지가 표시되었다.
      4. Excel -> PDF, PPT -> PDF, Word -> PDF 모듈이 작동하지 않았다.
    • 원인 분석
      1. Windows 7, Vista, Windows Server 2008에서 Windows Service는 Session0라고 불리는 session (or something)에서 구동이 된다. Session0는 Desktop에서 구동되는 프로그램에 접근이 불가능한 영역(Desktop-less wasteland)인데 개발된 Windows Service는 Desktop Session에서 구동되는(Desktop-ed session) Office Program인 관계로 Windows Service가 정상적으로 작동되지 않았던 것이다.
        (참고 URL : http://stackoverflow.com/questions/241190/vista-office-interop-not-working)
    • 처리 방안
      1. 첫 번째 처리 내용 : System Profile을 위한 desktop folder를 생성한다.
        이 방법은 msdn에서 확인한 방법으로서 H.Ogawa가 제시한 방법이다
        http://social.msdn.microsoft.com/Forums/en/innovateonoffice/thread/b81a3c4e-62db-488b-af06-44421818ef91

        아래의 경로에서 볼 수 있듯이 systemprofile이라는 폴더에 Desktop이라는 폴더를 만들고 해당 폴더 권한에 Everyone을 추가하고 모든 권한을 주면 된다.

        c:\Windows\SysWOW64\config\systemprofile\Desktop, or
        c:\Windows\System32\config\systemprofile\Desktop

        개발된 Windows Service 프로그램이 64bit로 빌드하였으면 SysWOW64에 Desktop을 등록하고 그렇지 않으면 System32에 등록하면 된다.

        => 처리 후 테스트 결과 : Excel, Word는 모두 정상적으로 작동을 하였으나 Powerpoint는 여전히 동작하지 않았다. 그래서 아래의 처리 방식을 추가로 처리하였다.
      2. 두 번째 처리 내용 : 1의 방법에도 여전히 Powerpoint가 구동되지 않았다.
        Powerpoint가 구동되기 위해서는 User Profile 정보가 필요한데 Windows Service로 구동을 하다 보니 충분한 User Profile 정보를 가져올 수 없어서 에러가 발생했던 것이다. (참고 URL : http://stackoverflow.com/questions/729609/powerpoint-interop-fails-in-a-windows-service-but-works-fine-in-a-windows-form-a)

        이에 대한 처리를 위해서, Windows Service에 등록되어 있는 Program의 속성 창에서 "로그온(Logon)" Tab을 클릭하여 "서비스와 데스크톱 상호 작용 허용"을 선택하면 Powerpoint도 이상 없이 구동된다.

      3. 추가 사항 : 1과 2의 방식을 통해서 Windows Service가 정상적으로 구동이 되었더니 다음과 같은 화면이 자꾸 표시되는 현상이 발생을 하였다.



        Windows Service가 구동되는 Session0에서 Word, Powerpoint등의 프로그램이 메세지를 발생시켜서 위의 화면이 표시되는 것으로 추측이 되었다.

        위의 메세지를 발생시키는 것은 다른 Windows Service에 의한 것으로서 Service 이름은 "Interactive Services Detection"이다. 해당 서비스는 "대화형 서비스에 대한 사용자 입력의 사용자 알림을 사용할 수 있도록 하는 서비스"로서 해당 서비스를 사용하지 않도록 Service 설정을 하면(사용안함으로 설정)된다.



    2012년 8월 14일 화요일

    IIS7.x에서 FluorineFX가 정상적 작동되지 않는 경우

    • 환경 : FluorineFX, Flash Builder 4.5, IIS 7.5
    • 개요 : FluorineFX를 통해서 Server Module을 구성하고 Flash Builder를 통해서 Client Module을 구성하여 IIS 7.5에 Porting을 하면 "BadVersion" 오류가 발생하였다.
    • 증상
      1. FluorineFX에서 제공하는 Sample - FluorineFX v1.0.0.15 installer를 설치하면 생성되는 샘플 코드 (설치폴더\Samples\Flex\Remoting\ArrayCollection) - 을 Visual Studio 2008에서 ASP.NET Development Server를 통해서 실행하면- 즉 Debug을 실행하면 - 정상적으로 구동이 된다.
      2. Visual Studio 2008을 통해서 웹사이트를 게시하여 IIS에서 구동을 하면
        BadVersion 오류가 발생한다
      3. Fiddler를 통해서 Gateway.aspx의 결과 값이 리턴되는 것을 확인해 보면
        - 정상적인 경우 : Content-Type이 "application/x-amf"으로 표시된다.
        - 오류가 있는 경우 : Content-Type이 "text/html"로 표시된다.
    • 원인 분석
      1. 정상적인 경우와 오류가 있는 경우의 Gateway.aspx가 리턴되는 값이 서로 틀린 것을 보고 IIS의 설정 상에 문제가 있는 것으로 짐작을 하게 되었으며 응용프로그램 풀의 설정에서 "관리되는 파이프라인 모드"를 "클래식"으로 바꾸니까 IIS에서도 정상적으로 실행이 되었다.
      2. 포팅된 웹사이트의 응용 프로그램 풀은 "FluorineFX_Test"로 설정을 하였으며
        원인은 FluorineFX_Test의 "관리되는 파이프라인 모드"가 기본적으로 "통합"으로
        설정이 되어 있기 때문이다.
      3. "Managed Pipeline mode"는 "integrated"와 "Classic"으로 설정이 되는데
        IIS 6.0 이전에는 "Classic"으로 관리가 되었다고 한다. Classic으로 관리가 되면
        ASP.NET 페이지는 ISAPI Extension과 ISAPI filters를 통해서 컨트롤이 되는 것으로서 통합 모드를 사용하는 것 보다는 관리상이나 성능상에서 많은 손해를 보게 된다고 한다.
      4. 이전에 만들어진 ASP.Net 프로그램이 IIS 7.x에서 정상적으로 구동이 되지 않는 경우에 "클래식"으로 설정을 하게 되면 정상적으로 작동이 된다. 결과적으로 FluorineFX는 이전에 만들어진 ASP.Net 코드이기 때문에 FluorineFX가 자동으로 생성하는 Web.Config의 내용이 IIS 6.0 이전의 기준에 맞춰져 있기 때문인 것이다.
    • 처리 방안
      1. 첫 번째 방법 : "관리되는 파이프라인 모드"를 "클래식"으로 설정한다.
        => 이렇게 하면 정상적으로 구동이 되기는 하지만 IIS 7.x의 성능을 제대로 활용하지 못하게 된다.
      2. 두 번째 방법 : IIS6 기준의 web.confing를 IIS7 기준으로 migration 한다.
        =>  %systemroot%\system32\inetsrv\APPCMD.EXE migrate config "응용프로그램풀 이름/" (주의할 점 => 응용프로그램풀 이름 뒤에 "/"가 들어가는 것을 주의한다.)
    • web.config의 변화

      migration을 하고 난 이후에 system.webServer/modules 에
      <add name="FluorineGateway" type="FluorineFx.FluorineGateway, FluorineFx" preCondition="managedHandler" /> 이 추가되었다.