[C#] มาดูกันว่า User Remote เข้ามาเปิดใช้ Application จากเครื่องไหน

ก่อนอื่นมาดูปัญหากันก่อนครับ ว่าทำไมถึงต้องไปไล่ดูว่า มีการ Remote จากเครื่อง User เพื่อมาใช้งาน Application ที่ติดตั้งบนเครื่อง Server หรือป่าว ? เพราะ IT ของลูกค้า อยากรู้ว่ามีใครใช้งานในระบบบ้าง แล้วใช้งานที่เครื่องไหน แต่บังเอิญว่ารอบนี้ ตัว Application ที่พัฒนาถูกไปติดตั้งบรเครื่อง Windows Server พอ User Remote เข้ามาใช้งาน ปรากฏว่าระบบลง Log และ Active User มาจากเครื่อง Serer ที่เป็น Windows Server ทั้งหมดเลยครับ โดยคำสั่ง C# ที่ใช้ดึงว่าเครื่องที่ Run Application อยู่ ชื่อเครื่องอะไร เป็นคำสั่งที่มีใน .Net Framework API ตามตัวอย่าง Code ด้านล่างเลยครับ

String ComputerName = Environment.MachineName;

มาที่โจทยฺ์ใหม่บ้าง เพราะ คำสั่ง Environment.MachineName; มันมีข้อจำกัด ถ้าเอา Application ไปดิดตั้งบน Windows Server มันจะไม่รู้ว่า User Remote มาจากเครื่องไหนครับ คำสั่งนี้จะดึงเฉพาะ แต่ชื่อเครื่อง ของ Server แทน โดยโจทย์ที่ทาง IT ของลูกค้าต้องการ ในกรณีที่มีการ Remote เข้ามาใช้งาน Application มีรูปแบบ ดังนี้ครั

ชื่อเครื่องปลายทาง(ชื่อเครื่องต้นทาง)

หลังจากรู้โจทย์แล้ว มาดูดีกว่าครับ ว่า C# ไม่สิต้องบอกว่า .Net Framework ได้เตรียมอะไรมาช่วยไว้บ้างครับ

  • ตัว System.Windows.Forms.SystemInformation.TerminalServerSession เป็นตัวที่บอกว่า Application ที่เขียนขึ่น Run ผ่่าน Remote Desktop หรือป่าวครับ ถ้าใช่ Return True ถ้าไม่ใช่ Return False ครับ
  • ตัว Remote Desktop Services API - เอาไว้ช่วยดึงค่าบางอย่าง มาจาก Protocal RDP ครับ

Code ที่ได้ปรับปรุง

  • Method GetComputerName() อันนี้เป็น Method ที่เราเปิดให้คนภายนอกใช้นะครับ
public static String GetComputerName() {
    String ComputerName;
    //ตรวจสอบว่า Session ที่เข้ามา เกิดจากการ Remote หรือป่าว ?
    if (System.Windows.Forms.SystemInformation.TerminalServerSession) {
        //ถ้ามาจากการ Remote เข้ามา ดึงชื่อเครื่อง โดยมี Pattern
        //Pattern >> เครื่องปลายทาง(เครื่องต้นทาง)
        //เช่น CHATRI-NGAM(AdminpingNBD)
        //Note: เครื่องต้นทาง ดึงจาก GetTerminalServerClientNameWTSAPI() ซึ่งเรียก "Wtsapi32.dll"
        ComputerName = Environment.MachineName + "(" + GetTerminalServerClientNameWTSAPI () + ")";
    } else {
        //ดึงชื่อเครื่องของ Program ที่ Run อยู่
        ComputerName = Environment.MachineName;
    }
    logger.Debug ("Remote Access from " + ComputerName);
    return ComputerName;
}
  • Helper GetTerminalServerClientNameWTSAPI และ WTSQuerySessionInformation เอาไว้ช่วยดึงค่าที่ต้องการจาก RDP Service ครับ
#region Get Remote Machine Name
private static string GetTerminalServerClientNameWTSAPI () {

    const int WTS_CURRENT_SERVER_HANDLE = -1;

    IntPtr buffer = IntPtr.Zero;
    uint bytesReturned;

    string strReturnValue = "";
    try {
        WTSQuerySessionInformation (IntPtr.Zero, WTS_CURRENT_SERVER_HANDLE, WTS_INFO_CLASS.WTSClientName, out buffer, out bytesReturned);
        strReturnValue = System.Runtime.InteropServices.Marshal.PtrToStringAnsi (buffer);
    } finally {
        buffer = IntPtr.Zero;
    }

    return strReturnValue;
}

[System.Runtime.InteropServices.DllImport ("Wtsapi32.dll")]
private static extern bool WTSQuerySessionInformation (System.IntPtr hServer, int sessionId, WTS_INFO_CLASS wtsInfoClass, out System.IntPtr ppBuffer, out uint pBytesReturned);

enum WTS_INFO_CLASS {
    WTSInitialProgram,
    WTSApplicationName,
    WTSWorkingDirectory,
    WTSOEMId,
    WTSSessionId,
    WTSUserName,
    WTSWinStationName,
    WTSDomainName,
    WTSConnectState,
    WTSClientBuildNumber,
    WTSClientName,
    WTSClientDirectory,
    WTSClientProductId,
    WTSClientHardwareId,
    WTSClientAddress,
    WTSClientDisplay,
    WTSClientProtocolType

}
#endregion

ผลการทดสอบ

  • เมื่อลองเปิด Application ผ่าน Remote Desktop มันแสดงขึ้น ตาม Requirement ที่ตกลงกันไว้ข้างต้น ดังรูป

Reference


Discover more from naiwaen@DebuggingSoft

Subscribe to get the latest posts to your email.