3

Is there any class available to get a remote PC's date time in .net? In order to do it, I can use a computer name or time zone. For each case, are there different ways to get the current date time? I am using Visual Studio 2005.

bluish
  • 26,356
  • 27
  • 122
  • 180
David.Chu.ca
  • 37,408
  • 63
  • 148
  • 190
  • How is the remote PC connected to your machine? Through a network? Through the web? – Pekka May 14 '10 at 19:05
  • The connect is through network. I can ping to the box by machine name or ip. – David.Chu.ca May 15 '10 at 03:05
  • 1
    Actually, I had SQL query to get remote time (SELECT GetDateTime()) from remote PC before I update data back and also wanted to show the remote date time to user. The query was called every 2 minutes and I got some exceptions (may be caused by threading from timer on the form). That's why I am thinking to use any other alternative way to get remote date time. – David.Chu.ca May 15 '10 at 03:09
  • possible duplicate of [Get the exact time for a remote server](http://stackoverflow.com/questions/1008111/get-the-exact-time-for-a-remote-server) – Jacob Jul 26 '12 at 02:59

5 Answers5

5

I give you a solution which uses WMI. You may or may not need the domain and security information:

try
{
    string pc = "pcname";
    //string domain = "yourdomain";
    //ConnectionOptions connection = new ConnectionOptions();
    //connection.Username = some username;
    //connection.Password = somepassword;
    //connection.Authority = "ntlmdomain:" + domain;

    string wmipath = string.Format("\\\\{0}\\root\\CIMV2", pc);
    //ManagementScope scope = new ManagementScope(
    //    string.Format("\\\\{0}\\root\\CIMV2", pc), connection);
    ManagementScope scope = new ManagementScope(wmipath);
    scope.Connect();

    ObjectQuery query = new ObjectQuery(
        "SELECT * FROM Win32_LocalTime");

    ManagementObjectSearcher searcher =
        new ManagementObjectSearcher(scope, query);

    foreach (ManagementObject queryObj in searcher.Get())
    {
        Console.WriteLine("-----------------------------------");
        Console.WriteLine("Win32_LocalTime instance");
        Console.WriteLine("-----------------------------------");

        Console.WriteLine("Date: {0}-{1}-{2}", queryObj["Year"], queryObj["Month"], queryObj["Day"]);
        Console.WriteLine("Time: {0}:{1}:{2}", queryObj["Hour"], queryObj["Minute"], queryObj["Second"]);
    }
}
catch (ManagementException err)
{
    Console.WriteLine("An error occurred while querying for WMI data: " + err.Message);
}
catch (System.UnauthorizedAccessException unauthorizedErr)
{
    Console.WriteLine("Connection error (user name or password might be incorrect): " + unauthorizedErr.Message);
}
bluish
  • 26,356
  • 27
  • 122
  • 180
Tim Trout
  • 1,062
  • 12
  • 20
2

Since WMI code would be very slow, you can use the below code to get faster results

            string machineName = "vista-pc";

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.FileName = "net";
            proc.StartInfo.Arguments = @"time \\" + machineName;
            proc.Start();
            proc.WaitForExit();

            List<string> results = new List<string>();
            while (!proc.StandardOutput.EndOfStream)
            {
                string currentline = proc.StandardOutput.ReadLine();
                if (!string.IsNullOrEmpty(currentline))
                {
                    results.Add(currentline);
                }
            }

            string currentTime = string.Empty;
            if (results.Count > 0 && results[0].ToLower().StartsWith(@"current time at \\" +                                               machineName.ToLower() + " is "))
            {
                currentTime = results[0].Substring((@"current time at \\" + machineName.ToLower() + " is                             ").Length);

                Console.WriteLine(DateTime.Parse(currentTime));
                Console.ReadLine();
            }
Brad Larson
  • 170,088
  • 45
  • 397
  • 571
Kevin M
  • 5,436
  • 4
  • 44
  • 46
1

You can use remote WMI and the Win32_TimeZone class. You do need to have permission to execute WMI queries on that machine. Avoid hassle like this by working with UTC instead of local time.

bluish
  • 26,356
  • 27
  • 122
  • 180
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

On a Windows machine there is net time \\<remote-ip address> to get the time of a remote machine. You could use that to find the remote system time, if you want code you can wrap it up in the function to execute the shell (DOS) functions in C#.

bluish
  • 26,356
  • 27
  • 122
  • 180
anijhaw
  • 8,954
  • 7
  • 35
  • 36
0

You can use pinvoke to NetRemoteTOD native API. Here is a small PoC.

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;

[StructLayout(LayoutKind.Sequential)]
struct TIME_OF_DAY_INFO
{
    public uint elapsedt;
    public int msecs;
    public int hours;
    public int mins;
    public int secs;
    public int hunds;
    public int timezone;
    public int tinterval;
    public int day;
    public int month;
    public int year;
    public int weekday;
}

class Program
{
    [DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
    private static extern int NetRemoteTOD(string uncServerName, out IntPtr buffer);

    [DllImport("netapi32.dll")] 
    private static extern void NetApiBufferFree(IntPtr buffer);

    internal static DateTimeOffset GetServerTime(string serverName = null)
    {
        if (serverName != null && !serverName.StartsWith(@"\\"))
        {
            serverName = @"\\" + serverName;
        }

        int rc = NetRemoteTOD(serverName, out IntPtr buffer);
        if (rc != 0)
        {
            throw new Win32Exception(rc);
        }

        try
        {
            var tod = Marshal.PtrToStructure<TIME_OF_DAY_INFO>(buffer);
            return DateTimeOffset.FromUnixTimeSeconds(tod.elapsedt).ToOffset(TimeSpan.FromMinutes(-tod.timezone));
        }
        finally
        {
            NetApiBufferFree(buffer);
        }
    }

    static void Main(string[] args)
    {
        Console.WriteLine(DateTimeOffset.Now);
        Console.WriteLine(GetServerTime());
        Console.WriteLine(GetServerTime("host1"));
        Console.WriteLine(GetServerTime("host2.domain.tld"));
        Console.ReadLine();
    }
}
Kirill Kovalenko
  • 2,121
  • 16
  • 18