DuraMap-Xr 설치자(Installer)

GIS 엔진인 DuraMap-Xr을 쉽고 간단하게 설치할 수 있는 설치 프로그램입니다. 아래의 파일을 다운로드 받아 실행해 클릭만으로 간단히 DuraMap-Xr을 설치할 수 있습니다.



좀더 자세히 설명 드리면, 먼저 설치 프로그램을 실행하면 다음과 같은 프로그램이 표시됩니다.

처음 설치할 경우 Install 버튼을 클릭해 설치하면 되고, 버전업 등과 같은 업데이트는 Update 버튼을 클릭하면 됩니다. 그리고 깨끗히 제거 하기 위해서 Remove 버튼을 클릭하면 됩니다.

이 설치자는 Windows 10 64Bits에서 정상적인 작동을 확인하였습니다. 설치나 삭제 등에서 문제가 발생할 경우에 대한 기술지원은 댓글을 이용해 주시기 바랍니다.

[C#] ActiveX 객체가 담긴 파일의 경로 얻기

ActiveX 객체는 ocx나 dll 파일에 담겨 있는데요. 이 ActiveX 객체를 등록(regsvr32.exe를 통해 직접 등록되거나 설치 파일 등을 통해 등록)될 경우 객체 ID를 통해 해당 ActiveX 파일의 전체 경로를 파악해야 할 필요가 있습니다. 이때 사용하는 함수입니다.

private static string GetFilePathOfActiveX(string comName)
{
    RegistryKey comKey = Registry.ClassesRoot.OpenSubKey(comName + "\\CLSID");
    if (comKey == null) return null;

    string clsid = (string)comKey.GetValue("");
    RegistryKey subKey = Registry.ClassesRoot.OpenSubKey("CLSID\\" + clsid + "\\LocalServer32");

    if (subKey == null) {
        subKey = Registry.ClassesRoot.OpenSubKey("CLSID\\" + clsid + "\\InprocServer32");
    }

    if (subKey == null)
    {
        subKey = Registry.ClassesRoot.OpenSubKey("WOW6432Node\\CLSID\\" + clsid + "\\InprocServer32");
    }

    if (subKey == null) return null;

    return (string)subKey.GetValue("");
}

위의 방식은 현재 Windows 10 64Bits 환경에서 작동하는 것을 확인했습니다. 다른 환경에서도 정상적으로 작동하는지 확인이 필요한데요. 혹 Win10 64Bits 환경 이외에서도 어떻게 작동하는지 댓글을 통해 언급해 주시면 좋겠습니다.

위의 함수는 아래처럼 사용할 수 있습니다.

MessageBox.Show(GetFilePathOfActiveX("XrMap.XrMapControl"));

[C#] 관리자 권한으로 상승하여 프로그램 실행

Windows 운영체제는 시스템의 몇가지 중요한 정보를 변경을 수행하기 위해서 관리자 권한으로 실행되어져야 합니다. 예를 들어 COM 기반의 컴포넌트를 등록하기 위한 경우 관리자 권한이 아닌 경우 등록이 실패합니다. 아래의 코드는 C#으로 개발된 프로그램을 실행할 때 관리자 권한으로 프로그램이 실행될 수 있도록 하는데, Program.cs의 Main() 함수에 대한 전체 코드입니다.

[STAThread]
static void Main()
{
    if (IsAdministrator() == false) // 관리자 권한으로 실행되지 않는 경우라면 ..
    {
        try
        {
            ProcessStartInfo procInfo = new ProcessStartInfo();
            procInfo.UseShellExecute = true;
            procInfo.FileName = Application.ExecutablePath;
            procInfo.WorkingDirectory = Environment.CurrentDirectory;
            procInfo.Verb = "runas";
            Process.Start(procInfo);
        }
        catch (Exception ex)
        {
            // 사용자가 프로그램을 관리자 권한으로 실행하기를 원하지 않을 경우에 대한 처리
            MessageBox.Show(ex.Message);
            return;
        }
    } else { // 처음부터 프로그램은 관리자 권한으로 실행되고 있는 경우라면 ..
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

위의 코드에서 IsAdministrator 라는 함수가 보이는데요. 이 함수는 아래와 같습니다.

public static bool IsAdministrator()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
            
    if(identity != null)
    {
        WindowsPrincipal principal = new WindowsPrincipal(identity);
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }

    return false;
}

위의 코드에서 참조하는 클래스를 인식하기 위해서는 다음을 import 문이 필요합니다.

using System.Security.Principal;
using System.Diagnostics;

GIS Server(GeoService-Xr)의 다중 DBMS Server 구성예

하나의 공간 서버(GeoService-Xr)에 대해 여러 개의 DBMS Server를 구성하는 경우에 대한 내용을 정리해 둡니다. 하드웨어적으로 다른 DBMS 서버는 물론이고, 동일한 서버에서 여러 개의 DBMS를 설치하거나, Port를 달리하거나 데이터베이스 명을 다르게 하여 분류해 사용하는 경우 모두 적용될 수 있습니다. 예를 들어 아래와 같은 구성 화면을 살펴보면..

하드웨어적으로 분리된 2개의 DBMS Server가 있으며, 192.168.0.200의 Server는 동일한 DBMS에서 Database 명을 달리해 구분하도록 되어 있습니다.

위의 구성에 대한 Geodata 설정 파일을 아래와 같습니다.

<?xml version="1.0" encoding="euc-kr"?>
<XrGeoData>
    <Connections>
        <Connection 
            name="db_server1" 
            type="postgis" 
            driverName="org.postgresql.Driver" 
            url="jdbc:postgresql://192.168.0.100:5432/gis" 
            user="postgres" 
            password="@#$%^" 
            count="32" 
        />

        <Connection
            name="db_server2" 
            type="postgis" 
            driverName="org.postgresql.Driver" 
            url="jdbc:postgresql://192.168.0.200:5432/gis" 
            user="postgres" 
            password="@#$%^" 
            count="32" 
        />

        <Connection
            name="db_server2_2" 
            type="postgis" 
            driverName="org.postgresql.Driver" 
            url="jdbc:postgresql://192.168.0.200:5432/gis2" 
            user="postgres" 
            password="@#$%^" 
            count="32" 
        />
  </Connections>

    <GeoDataList>
        <GeoData>
            <Name>ecl_facility</Name>
            <ConnectionString>db_server1://public."ecl_facility"</ConnectionString>
            <EPSG>5179
        </GeoData>

        <GeoData>
            <Name>swl_facility</Name>
            <ConnectionString>db_server2://public."swl_facility"</ConnectionString>
            <EPSG>5179
        </GeoData>
    </GeoDataList>
</XrGeoData>

위의 geodata 설정 내용 중 Connection의 name은 생략될 수 있으며, 만약 생략될 경우 type의 값으로 name이 대체됩니다.

개발한 Web OpenAPI를 Spring 프레임워크에서 사용할 때 ..

제목이 참 마땅히 지을만한것도 없고.. 어여 이 곳에 정리해 내 머리속에서 지워버리고자 하는 마음에 지은 제목입니다.

상황은.. jetty를 사용해 지도 OpenAPI를 만들었고, 이 OpenAPI를 Spring 프레임워크를 기본으로 하는 웹 시스템에서 사용하는데, AJAX의 POST 방식으로 OpenAPI를 호출합니다. 이때 이 OpenAPI를 Spring 프레임워크가 아닌 환경에서는 Cross Domain 문제가 발생하지 않습니다. 물론 발생하지 않도록 OpenAPI 서버에 조치를 해두었습니다. 그런데.. Spring 프레임워크에서는 Cross Domain 에러가 발생합니다. 신기한건.. AJAX의 GET 방식은 Cross Domain 에러가 발생하지 않고 POST 만 발생합니다.

먼저 Cross Domain 문제는 아래의 코드를 OpenAPI 서버(jetty를 활용하는 서버)에 적용하여 해결할 수 있었습니다. 코드가 긴데.. 불필요한 코드가 있을거라 생각되지만 일단 모두 기재합니다.

FilterHolder holder = new FilterHolder(CrossOriginFilter.class);

holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
holder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD");
holder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");
holder.setName("cross-origin");

FilterMapping fm = new FilterMapping();

fm.setFilterName("cross-origin");
fm.setPathSpec("*");

handler.addFilter(holder, fm);

위의 코드를 OpenAPI 서버에 적용하면 더 이상 Cross Domain 에러가 발생하지 않습니다만, 여전이 문제가 있습니다. POST 방식으로 데이터를 전달 하는데.. 이 데이터의 형식이 일반적으로 흔한 FORM 형태로 전달되어야 합니다. 그런데 Spring에서는 payload라는 형식으로 전달됩니다. 이에 대한 문제는 클라이언트 웹단에서 AJAX 호출시 headers 옵션값을 추가적으로 지정해 주면 해결됩니다. 즉, 아래처럼요.

$.ajax({
    method: 'POST',
    url: url,
    data: ketData,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

솔찍히 Spring 프레임워크에서 발생하는 문제인지는 모르겠습니다. 단지 Spring 프레임워크가 아닌 환경에서는 문제가 발생하지 않았으므로, 아마도 Spring 프레임워크 환경에서 발생하는 문제라고 추측할 뿐이지만.. 여튼 이와 유사한 문제가 발생할 경우에 대한 해결책으로써 기록을 남깁니다.