2016-06-24 2 views
0

Windows 10 Pro 64 비트에서 지정된 프로세스 ID에 대한 유효한 DPI 인식 값을 검색하려고합니다. 내가 필요한 값은 PROCESS_DPI_AWARENESS 중 하나이며 WinAPI GetProcessDpiAwareness 기능을 사용할 수 있습니다.C#에서 GetProcessDpiAwareness를 호출하면 항상 오류가 반환됩니다. E_INVALIDARG

VS 2015에서 간단한 한 창 C# WPF 응용 프로그램을 작성했습니다. 관심이있는 프로세스 ID를 TextBox txtProcessID에 입력하면 결과가 TextBlock txtResult에 표시됩니다. txtProcessID 버튼 :

private const int S_OK = 0; 
private enum PROCESS_DPI_AWARENESS 
{ 
    PROCESS_DPI_UNAWARE = 0, 
    PROCESS_SYSTEM_DPI_AWARE = 1, 
    PROCESS_PER_MONITOR_DPI_AWARE = 2 
} 
[DllImport("Shcore.dll")] 
private static extern int GetProcessDpiAwareness(IntPtr hprocess, out PROCESS_DPI_AWARENESS value); 

private void btnGetDPIAwareness_Click(object sender, RoutedEventArgs e) 
{ 
    int procIDint = int.Parse(txtProcessID.Text); 
    IntPtr procID = new IntPtr(procIDint); 
    PROCESS_DPI_AWARENESS value; 
    int res = GetProcessDpiAwareness(procID, out value); 
    if (res == S_OK) 
     txtResult.Text = value.ToString(); 
    else 
     txtResult.Text = "Error: " + res.ToString("X"); 
} 

그러나 모든 프로세스에 대한 GetProcessDpiAwareness를 호출하면 항상 나에게 오류 E_INVALIDARG를 제공합니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

+4

[GetProcessDpiAwareness] (https://msdn.microsoft.com/en-us/library/windows/desktop/dn302113.aspx) : * "hprocess : ** 처리중인 ** 처리중인 쿼리 **" * - API는 맹목적으로 ID를 전달하는 반면 핸들은 예상합니다. 프로세스 ID에서 프로세스 핸들을 얻으려면 [OpenProcess] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684320.aspx)를 호출하십시오. – IInspectable

+2

https://msdn.microsoft.com/en-us/library/system.diagnostics.process.handle(v=vs.110).aspx –

답변

4

GetProcessDpiAwareness의 설명서에서 첫 번째 매개 변수는 프로세스 ID가 아니라 프로세스 핸들입니다. 너는 OpenProcess을 필요로하고, 너는 그때 원하는 정보를 얻는다 CloseHandle. (AP/호출 서명, 일반적으로 관리 코드에 IntPtr 될 것이다 h 또는 lp로 시작하는 변수 이름을 정의 할 때.)

에서와 마찬가지로 : 쉬운 방법은 사용하는 것입니다 있지만

private const int PROCESS_QUERY_INFORMATION = 0x0400; 
private const int PROCESS_VM_READ = 0x0010; 

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

[DllImport("Kernel32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)] 
private static extern bool CloseHandle(IntPtr handle); 

private const int S_OK = 0; 
private enum PROCESS_DPI_AWARENESS 
{ 
    PROCESS_DPI_UNAWARE = 0, 
    PROCESS_SYSTEM_DPI_AWARE = 1, 
    PROCESS_PER_MONITOR_DPI_AWARE = 2 
} 
[DllImport("Shcore.dll")] 
private static extern int GetProcessDpiAwareness(IntPtr hprocess, out PROCESS_DPI_AWARENESS value); 

private PROCESS_DPI_AWARENESS GetDpiState(uint processId) 
{ 
    IntPtr handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId); 
    if (handle != IntPtr.Zero) 
    { 
     PROCESS_DPI_AWARENESS value; 
     int result = GetProcessDpiAwareness(handle, out value); 
     if (result == S_OK) 
     { 
      System.Diagnostics.Debug.Print(value.ToString()); 
     } 
     CloseHandle(handle); 
     if (result != S_OK) 
     { 
      throw new Win32Exception(result); 
     } 
     return value; 
    } 
    throw new Win32Exception(Marshal.GetLastWin32Error()); 
} 

System.Diagnostics.Process은 다음과 같습니다 :

System.Diagnostics.Process proc = Process.GetProcessById(processId); 
PROCESS_DPI_AWARENESS value; 
int res = GetProcessDpiAwareness(proc.Handle, out value); 
+0

PROCESS_VM_READ는 필요하지 않습니다. – Elmue

+0

중요 : GetProcessDpiAwareness()는 다른 프로세스에서 해당 정보를 얻기 위해 서비스 (SYSTEM/NT AUTHORITY)에서 실행될 경우 작동하지 않습니다. 항상 E_INVALIDARG를 반환합니다 – Elmue

0

예, 필자는 생략했습니다. 프로세스 핸들을 GetProcessDpiAwareness에 전달해야했습니다. 난 그냥 내 질문 아래의 첫 번째 두 의견에 따라 내 자신의 작업 코드를 작성했습니다 :

int procID = int.Parse(txtProcessID.Text); 
Process process = Process.GetProcessById(procID, "."); 
PROCESS_DPI_AWARENESS value; 
int res = GetProcessDpiAwareness(process.Handle, out value); 
if (res == S_OK) 
    txtResult.Text = value.ToString(); 
else 
    txtResult.Text = "Error: " + res.ToString("X"); 
process.Close(); 

한 추가 코멘트 : 그것은 다른 프로세스에 접근 문제를 방지하기 위해 관리자 권한으로이 코드를 실행하는 것이 좋습니다.

+4

아마도이 코드를 관리자 권한으로 실행하지 않아도됩니다. 해당 [액세스 권한] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms684880.aspx)을 [OpenProcess] (https://msdn.microsoft.com/en-us/)로 전달하십시오. us/library/windows/desktop/ms684320.aspx). 'PROCESS_QUERY_LIMITED_INFORMATION'으로 충분해야합니다. – IInspectable

+0

@IInspectable, .NET 관리 방식을 사용하여 다른 프로세스에 액세스합니다. 이 환경에서이 작업을 수행하는 방법을 알고 있습니까? 참고 사항 : 관리자 권한으로 내 미니 도구를 실행하는 것은 내 dev pc 내에서 모두 완료되므로 내게 문제가되지 않습니다. – TecMan

+0

[System.Diagnostics를 사용할 때 요청한 액세스 권한을 제공하는 방법이 아닌 것 같습니다. .Process] (https://msdn.microsoft.com/en-us/library/system.diagnostics.process.aspx) 클래스를 참조하십시오. 하지만 [theB의 대답] (http://stackoverflow.com/a/38012663/1889329)에서 설명한 것처럼 OpenProcess를 P/Invoke 할 수 있습니다. – IInspectable

관련 문제