2009-08-19 1 views
5

나는 Mono에서 어느 시점에서 실행하고 싶은 WinForms 응용 프로그램을 가지고 있습니다. 그러나 user32.dll에 대해 일부 P/Invoke를 사용하고있어 명백한 문제가 발생할 수 있습니다.모노를 실행할 때 "무시"P/Invoke

그러나 중요한 기능은 아니며 단지 맛을 내기위한 것입니다. 그래서 Mono를 실행할 때 무시하고 싶습니다.

#if 지시문을 사용할 수는 있지만 두 개의 다른 어셈블리를 제공해야한다는 것을 알고 있습니다. Mono에서 실행 중이면 Runtime을 확인할 수 있지만 기능에 대한 선언을 제거하는 데는 도움이되지 않습니다.

이렇게 궁금합니다. "모노를 실행 중이면 완전히 무시하십시오"라고 말할 수있는 방법이 있습니까? 도움이되는 경우 : P/Invoke 항목은 별도의 .cs 파일에 있으며 부분 클래스로 구현됩니다.

문제의 소스 코드는 여기에 있습니다 : http://pastie.org/588940
그것은 시스템 메뉴에 항목을 추가 할 수의 WndProc 메시지를 무시하고 내 기본 폼의 일부입니다. (다른 것들은 잘랐다.) 내 문제는 WndProc 물건이 쉽지만, 두 개의 private extern 선언을 어떻게 처리해야할지 모르겠다. 나는 Mono를 호출하지 않는 다른 (정적 인) 클래스에 넣을 수 있는가? 아니면 러시아 룰렛일까요?

+1

Swiki가 이미 위키 소프트웨어의 이름이라는 것을 알고 있습니까? http://en.wikipedia.org/wiki/Swiki –

+0

이미 등록을 마친 후에야 조회수가 증가하고 있습니다. 현재 1.0 용으로 이름을 바꾸는 것을 고려하고 있습니다. –

답변

8

플랫폼 종속적 인 내용을 인터페이스에 캡슐화하지 않은 다음 왜 현재 플랫폼에 대한 "올바른"구현을 얻는 지 알 수 있습니다. 그런 다음 호출 코드가 blithely를 사용할 수 있으며 원할 때 Mono를 실행할 비트를 점진적으로 채울 수 있습니다. 나는 것 이상 희망 당신도 P/호출 비트를 포함하는 클래스를로드하지 않을 경우, 당신은 괜찮을해야은 ...

편집 :

내가 볼 수없는 이유는이 방법은 안 비록 당신이 공장을 필요로하지 않을지라도. 여기에 내가 할 줄 작업은 다음과 같습니다

MainForm.cs :

PlatformServicesFacade.InitializeSystemMenu(); 

IPlatformServices.cs :

public interface IPlatformServices 
{ 
    void InitializeSystemMenu(); 
} 

MonoPlatformServices.cs :

public class MonoPlatformServices : IPlatformServices 
{ 
    // Prevent early type initialization 
    static WindowsPlatformServices() {} 

    public void InitializeSystemMenu() 
    { 
     // Maybe log what you would have done? 
    } 
} 

WindowsPlatformServices.cs :

public class WindowsPlatformServices : IPlatformServices 
{ 
    // Prevent early type initialization 
    static WindowsPlatformServices() {} 

    public const Int32 SystemMenuAboutSWikiId = 1000; 
    [DllImport("user32.dll")] 
    private static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); 
    [DllImport("user32.dll")] 
    private static extern bool InsertMenu(IntPtr hMenu, Int32 wPosition, 
              Int32 wFlags, Int32 wIDNewItem, 
              string lpNewItem); 

    public void InitializeSystemMenu() 
    { 
     const Int32 MF_SEPARATOR = 0x800; 
     const Int32 MF_BYPOSITION = 0x400; 

     IntPtr systemMenuPtr = GetSystemMenu(Handle, false); 
     InsertMenu(systemMenuPtr, 5, MF_BYPOSITION | MF_SEPARATOR, 0, ""); 
     InsertMenu(systemMenuPtr, 6, MF_BYPOSITION, SystemMenuAboutSWikiId, 
        "About SWiki..."); 
    } 
} 

PlatformServicesFacade.cs :

public class PlatformServicesFacade 
{ 
    private static readonly IPlatformServices services; 

    static PlatformServiceFacade() 
    { 
     services = RunningOnWindows() ? new WindowsPlatformServices() 
      : (IPlatformServices) new MonoPlatformServices(); 
    } 

    public static void InitializeSystemMenu() 
    { 
     services.InitializeSystemMenu(); 
    } 
} 

나는 그것을하지 않는 경우, 잘못된 무슨 일이 일어나고 있는지 :)

2

런타임을 확인 알려주세요 ... 작업을해야 생각 은 실행 가능한 해결책처럼 보인다 . P/Invoke 함수 선언을 제거하지 않으려는 이유가 있습니까?

+0

방금 ​​호출되지 않고 무작위로 응용 프로그램이 중단되는지 확인하고 싶습니다. –

+0

공개하지 마십시오. 플랫폼 특정 변형 – skolima

4

일부 환경 속성에는 System.Environment.OSVersion.Platform과 같은 정보가있을 수 있습니다. 또는 if (Type.GetType ("Mono.Runtime")! = null)

"실행 플랫폼을 찾는 방법"을 참조하십시오. 및 "모노로 실행 중인지 어떻게 확인할 수 있습니까?": http://www.mono-project.com/FAQ:_Technical

+0

고마워. 내 문제. "어떻게하면 외부 메서드의 _declaration_을 런타임에 실행되는 조건부 블록에 넣을 수 있습니까?" –

2

나는 Mono 녀석들로부터 가장 좋은 내기가 M/Invoke 일 것이라고 생각한다. (여전히 Mono SVN에서만 새롭다.) 그러나 나는 Mono Distribution에 들어가는 데 도움을 줄 것이라고 확신한다. :)

+0

나는 그렇게 생각합니다. :) 그러나 P/Invoke는 실제로 사용하고 싶은 것 중 하나입니다. 다른 방법은 없으며 심지어는 최소한으로 만 사용해야합니다. –

관련 문제