2015-02-02 2 views
1
private struct TOKEN_USER 
    { 
     internal SID_AND_ATTRIBUTES User; //Compiler warning comes from here. 
    } 

[StructLayout(LayoutKind.Sequential)] 
private struct SID_AND_ATTRIBUTES 
    { 
     internal IntPtr Sid; 
     private int Attributes; 
    } 

기본값으로 구조를 초기화를해야합니다 :필드 '필드'에 할당되지 않습니다, 항상 기본값

다음 구조에 포인터를 검색하기 위해 두 개의 필수 호출을
TOKEN_USER tokenUser = default(TOKEN_USER); 

: (질문과 관련 없음)을 사용하여 다음을 사용합니다.

GetTokenInformation(tokenhandle, TokenInformationClass.TokenUser, sid, sidlength, ref sidlength); 

그런 다음 다시 구조로 정렬합니다.

tokenUser = (TOKEN_USER)Marshal.PtrToStructure(sid, tokenUser.GetType()); 

작동하지만 컴파일러에서 TOKEN_USER의 'User'필드가 할당 취소되었다고 경고합니다.

public TOKEN_USER(SID_AND_ATTRIBUTES user) : this(user) 
     { 
     } 

그러나,이 컴파일되지 않는 오류 "생성자는 자신을 호출 할 수 없습니다"로 :

R 번호 나 생성자에서 초기화 제안합니다. 제 질문은 컴파일러의 요구 사항을 충족 시키거나 무시할 수 있도록 SID_AND_ATTRIBUTES (기본값)에 할당해야합니까?

테스트 프로그램은 :

[DllImport("kernel32.dll", SetLastError = true)] 
    private static extern IntPtr OpenProcess(
     int dwDesiredAccess, 
     [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, 
     int dwProcessId); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool OpenProcessToken(
     IntPtr processHandle, 
     int desiredAccess, 
     ref IntPtr TokenHandle); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool GetTokenInformation(
     IntPtr tokenHandle, 
     TokenInformationClass tokenInformationClass, 
     IntPtr tokenInformation, 
     int TokenInformationLength, 
     ref int ReturnLength); 

    [DllImport("advapi32.dll", SetLastError = true)] 
    private static extern bool IsValidSid(
     IntPtr SID); 


    private enum TokenInformationClass 
    { 
     TokenUser = 1, 
    } 

    private const int QueryInformation = 0x400; 

    private const int TokenRead = 0x20008; 

    private struct TOKEN_USER 
    { 
     internal SID_AND_ATTRIBUTES User; //Compiler warning comes from here. 
    } 

    [StructLayout(LayoutKind.Sequential)] 
    private struct SID_AND_ATTRIBUTES 
    { 
     internal IntPtr Sid; 
     private int Attributes; 
    } 



    internal static IntPtr GetProcessHandle() 
    { 
     foreach (Process p in Process.GetProcesses()) 
     { 
      using (p) 
      { 
       if (p.ProcessName == "explorer") 
       { 
        return OpenProcess(QueryInformation, false, p.Id); 
       } 
      } 
     } 
     return IntPtr.Zero; 
    } 

    public void Test() 
    { 
     IntPtr pHandle = GetProcessHandle(); 

     IntPtr tokenHandle = IntPtr.Zero; 
     OpenProcessToken(pHandle, TokenRead, ref tokenHandle); 

     int sidlength = 0; 
     GetTokenInformation(tokenHandle, TokenInformationClass.TokenUser, IntPtr.Zero, 
0, ref sidlength); 

     TOKEN_USER tokenUser = default(TOKEN_USER); 
     IntPtr sid = Marshal.AllocHGlobal(sidlength); 

     GetTokenInformation(tokenHandle, TokenInformationClass.TokenUser,sid, 
sidlength, ref sidlength); 

     tokenUser = (TOKEN_USER)Marshal.PtrToStructure(sid, tokenUser.GetType()); 


     if (IsValidSid(tokenUser.User.Sid)) 
     { 
      Debug.WriteLine("Valid!"); 
     } 
    } 
+0

전체 프로그램을 표시 할 수 있습니까? –

+0

@DavidHeffernan 전체 프로그램이 너무 축소되어 문제를 시연 할 수있는 테스트 프로그램을 만들었습니다. 프로세스 토큰을 사용하고 있으므로 반환 할 도우미 함수를 만들었습니다. 데모 용 "탐색기"프로세스 토큰. – SomeNickName

+0

'tokenUser = default (TOKEN_USER)'의 요점은 무엇입니까? 나중에'tokenUser'에 지정합니다. 컴파일러는 어떤 코드 행을 처리합니까? –

답변

4

이 당신은 반사로 또는 Marshal 클래스 (여기로) 일부 외부 메커니즘을 통해 초기화 유형을 사용하는 시간이 경고가 표시됩니다. 문제는 컴파일러가 필드 초기화 방법을 알 수 없다는 것입니다. 볼 수있는 것은 모두 유형 자체이며, 해당 필드를 초기화 할 유형은 없습니다.

값을 할당하지 않은 필드를 선언하면 코딩 실수가되기 때문에 컴파일러에서 대/소문자에 대한 경고를 생성합니다.

정확한 제안 R #이 무엇인지 확실하지 않지만, 무한 재귀 초기화를 생성하기 때문에 분명히 당신이 선언하는 것과 동일한 생성자 오버로드를 사용할 수 없습니다.

어떤 경우에는 : this() (즉, 기본 생성자 호출)을 사용하여 struct을 초기화하는 것이 좋습니다.하지만 생성자의 필드 또는 속성에 액세스하려는 문제를 처리하기위한 것이므로 초기화 됨 (this() 생성자를 호출하면 전체 개체가 초기화 됨) 어쩌면 R #이 "생각 중"이었을까요?


어쨌든,이 상황에서 내 접근 방식은 단순히 경고를 사용하지 않는 것입니다. I do은 컴파일러가 알지 못하는 방식으로 필드를 초기화합니다. #pragma warning 지시문을 사용하여이를 수행 할 수 있습니다. 예 :

private struct TOKEN_USER 
{ 
    #pragma warning disable 0649 
    internal SID_AND_ATTRIBUTES User; 
    #pragma warning restore 0649 
} 

대답의 범위는 Suppressing “is never used” and “is never assigned to” warnings입니다. 그곳에는 왜 경고가 무력화되고 왜 안전한지에 대한 설명이 포함되어있는 것이 좋습니다. IMHO, 그게 아주 좋은 생각이다 어떤 경고를 비활성화 상황.

+0

감사! 나는 #pragma를 사용하지 않았다 ... 잘 알고있다. 그리고 네, R #은 컴파일 할 수없는 코드의 스 니펫을 제안합니다. 버그로보고하려고 생각했습니다. – SomeNickName

관련 문제