2009-12-11 6 views
4

C# console app 실행하기 64 비트 Vista에 썼습니다. 코드는 다음과 같습니다.pinvoke를 통해 GetPrivateProfileString을 사용할 수없는 이유는 무엇입니까?

class Class1 
{ 
    static void Main(string[] args) 
    { 
     Debug.Assert(File.Exists(@"c:\test.ini")); 
     StringBuilder sb = new StringBuilder(500); 
     uint res = GetPrivateProfileString("AppName", "KeyName", "", sb, sb.Capacity, @"c:\test.ini"); 
     Console.WriteLine(sb.ToString()); 
    } 
    [DllImport("kernel32.dll")] 
    static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, StringBuilder lpReturnedString, int nSize, string lpFileName); 
} 

큰 "DUH!" 대답은 없지만 왜 이것이 실패하는지 보지 못합니다. Debug.Assert 이외에,이 코드 pinvoke.net에 따르면 this page

답변

4

이 사람도 하루 종일 내 껍질을 깨고 있습니다. 난 정말 해결할 필요가없는 해결 방법을 찾은 것 : .ini 파일의 첫 번째 섹션 머리글 앞에 빈 줄을 삽입하십시오. 이제 앱을 실행하고 기대했던 값을보기 시작하지 않는지 확인하십시오.

이 버그가 분명히 수년간 주변에 있었음을 고려하면 MS는 지금까지 해결하지 못했습니다. 그러나 .ini 파일은 몇 년 전에 없어 졌다고합니다. MS가 .ini 파일 (예 : desktop.ini)을 사용하는 곳이 많기 때문에 당연히 재미 있습니다. 그러나 나는 desktop.ini 파일에 선행 빈 줄이 있다는 것을 알기 때문에 MS가 버그를 알고 있다고 생각합니다. 음 ...

+0

내가 XP Pro 32 비트에서이 코드를 실행하고 있음을 잊어 버렸습니다. – Lee

+0

방금 ​​GetPrivateProfileSectionW 및 GetPrivateProfileSectionNamesW를 시도했습니다. 둘 다 같은 방식으로 실패합니다. 흥미로운 점은 섹션 이름을 검색하려고 할 때 GetPrivateProfileStringW 또는 GetPrivateProfileSectionNamesW를 사용하여 가져온 첫 번째 섹션 만 반환된다는 것입니다. 나는 이것들을 충분히 재미있게 보냈다. CodePlex는 몇 가지 대체품이있는 것처럼 보입니다. 그 두 가지가 작동하지 않는다면 나는 내 자신을 굴릴 것이다. – Lee

+0

오 마이 맙소사! 네가 옳아! 내가 읽으려는 섹션은 INI 파일의 첫 번째 라인이 될 수 없습니다! 믿을 수 없는! 누가 알았겠습니까? 정말 고맙습니다. – Charles

0

에서 C#을 샘플에서 절단, n 크기는 UINT해야한다. 또한 그들은 그들의 예에서 절대 경로를 사용하고 있습니다.

그 차이점 이외에는 다른 것을 볼 수 없습니다.

그것은 잘못된 형식의 예외를 던지고 제공하는 문제를 해결하기 위해 X86을 대상 플랫폼을 설정하려고합니다. pinvoke.net에서

사용 예는 내가 볼 중요한 것은 당신이 n 크기에 대한 UINT뿐만 아니라 반환 값을 전달해야한다는 것입니다

[DllImport("kernel32.dll", CharSet=CharSet.Unicode)] 
    static extern uint GetPrivateProfileString(
    string lpAppName, 
    string lpKeyName, 
    string lpDefault, 
    StringBuilder lpReturnedString, 
    uint nSize, 
    string lpFileName); 


static void Main(string[] args) 
{ 
    StringBuilder sb = new StringBuilder(500); 
    uint res = GetPrivateProfileString("AppName", "KeyName", "", sb, (uint)sb.Capacity, @"c:\test.ini"); 
    Console.WriteLine(sb.ToString()); 
} 
+0

당신은 INT 대신 사용할 수 있습니다 size 인수에 sb.Capacity가 발생하는 것을 방지하기위한 결합. – Charles

+0

잘못된 형식 예외가 발생합니까? 또는 어떤 예외/오류가 던져지고/반환됩니까? –

+0

함수는 성공한 것처럼 보이지만 0을 반환합니다. Marshal.GetLastWin32Error를 검사하면 값은 1008입니다. == ERROR_NO_TOKEN – Charles

1

입니다. GetPrivateProfileString의 return 및 nSize 매개 변수는 부호가없는 32 비트 정수인 DWORD 값이기 때문입니다.

나는 개인적으로 PInvoke.net에 구문을 사용했습니다 :

[DllImport("kernel32.dll", CharSet=CharSet.Unicode)] 
static extern uint GetPrivateProfileString(
    string lpAppName, 
    string lpKeyName, 
    string lpDefault, 
    StringBuilder lpReturnedString, 
    uint nSize, 
    string lpFileName); 

또한,이 파일은 Windows 디렉터리에 위치하지 않는 장소에 파일의 전체 경로를 넣어해야합니다. 문서에서 :

이 매개 변수에 파일의 전체 경로가 포함되어 있지 않으면 시스템은 Windows 디렉토리에서 파일을 검색합니다.

1

경로를 지정하지 않으면 GetPrivateProfileString은 Windows 디렉터리에서 Test.ini를 찾습니다. 이 GetPrivateProfileString 같은

올드 API는 (A GetPrivateProfileStringW 기능이 비록)도 유니 코드를 처리하지 않습니다. Test.ini에 UTF 헤더 또는 유니 코드 문자가 포함되어 있으면 GetPrivateProfileString이 제대로 작동하지 않을 수 있습니다. 또한

, 비스타의 UAC는 "특별한"장소 까다로운 (C : \, C : \ WINDOWS, C : 등 \ 프로그램 파일)에있는 파일을 처리 할 수 ​​있습니다. Test.ini를 C : 드라이브의 루트가 아닌 폴더에 넣거나 UAC를 해제하십시오. UAC에서 제어하는 ​​폴더에서 .ini를 읽으려고 할 때 GetPrivateProfileString이 자동으로 실패하는 것에 대해 설명하는 thread on CodeProject이 있습니다.

+0

아니요. 그거 아니야. Windows 디렉터리에 복사했는데 행운이 없습니다. Debug.Assert (File.Exists ("Test.ini"))도 추가했습니다. 현재 작업 디렉토리에서 읽으려고합니다. – Charles

+0

빈 줄이 없지만 파일이 ANSI (UTF8 아님)로 저장되어 있으면 GetPrivateProfileString이 올바르게 작동합니다. –

0

어쩌면 당신은 당신이 P/호출의 걱정없이 정확히 할 것입니다 오픈 소스 솔루션을 찾고에 보일 것입니다. .NET을 대상으로 한 프로젝트는 nini입니다. 저는이 프로젝트를 사용하고 있습니다.

호프가 도움이 되었으면 안녕하세요, 탐.

+0

고마워,하지만 내 좌절감을 해결하려고 노력하고있어. 해결 방법을 찾지 못했다. – Charles

+0

@Charles : Ok ... 이것을 사용하는 방법에 대한 샘플이 포함 된 http://pinvoke.net/default.aspx/kernel32/GetPrivateProfileString.html을 보셨습니까? – t0mm13b

+0

그게 내가 내 코드를 붙여 넣은 곳이야. – Charles

0

test.ini 파일의 내용을 확인할 수 있습니까? 시도한 모든 단계를 감안할 때 데이터 파일의 형식이 잘못되었거나 (맞춤법이 잘못됨) 의심 스럽습니다. 즉, GetPrivateProfileString은 "작동 중"일 수 있지만 문자열을 찾지 못했을 수 있습니다. 당신이 게시 코드를 기반으로, 당신의 test.ini 파일은 다음과 비슷한 모습이 될 것

[프로그램 응용]
은 키 이름 = foo는 해당 페이지의 코멘트 섹션도 상태

+0

Nope. INI는 기술적으로 정확했지만 Lee는 수정 사항을 지적했습니다. - 내가 읽는 부분은 INI 파일의 첫 번째 줄에서 시작할 수 없습니다. – Charles

+0

.ini 파일의 시작 부분에서 Byte Order Marker를 발견하기 전에 주석을 작성 했어야합니다. 그 정보를 토대로, .ini 파일은 기술적으로 정확하지 않다고 말합니다. :-) –

관련 문제