|
皆様、回答ありがとうございます。 場合によって1,2秒程度のずれがあることが理解できました。 その後も対策を調べていたのですが dobon.net様のコード https://dobon.net/vb/dotnet/process/standardoutput.html を参考にして、 以下の手法で一見うまくいきそうなのですが、根本的な間違いや、やってはいけない操作等がありますでしょうか?
<1>管理者権限で起動 <2>元の参考ソースの通りNTPサーバから時刻取得 <3>PC時刻を校正 ←この時点で1秒未満のズレがあることが本件の質問案件でした <4>【w32tm /stripchart /computer:[NTPサーバ] /samples:1】をコマンド送信し、戻り値を取得
取得例) 13:47:40, d:+00.0182803s o:+00.5406896s [ |* ]
<5>o: の後に続く差分(+00.5406896)を取得し現在日時に対して差分をAddMillisecondsした値で再校正 <6>完了
再校正後例) 13:47:43, d:+00.0210491s o:+00.0011926s [ * ]
という結果でかなり差を縮めることができました。(できたように見えます)
<使ったソースの抜粋> objSck.Send(sdat, sdat.GetLength(0), 192.168.0.10, 123);
// NTPサーバから日時データ受信 Byte[] rdat = objSck.Receive(ref ipAny);
// 1900年1月1日からの経過時間(日時分秒) long lngAllS; // 1900年1月1日からの経過秒数 long lngD; // 日 long lngH; // 時 long lngM; // 分 long lngS; // 秒
// 1900年1月1日からの経過秒数計算 lngAllS = (long)( rdat[40] * Math.Pow(2, (8 * 3)) + rdat[41] * Math.Pow(2, (8 * 2)) + rdat[42] * Math.Pow(2, (8 * 1)) + rdat[43]);
if ((rdat[0] & 0xc0) == 0)//同期 { Outputlog(Logging.Lv6_INFO4, Logging.Typ2_SEND, "同期受信");
// 1900年1月1日からの経過(日時分秒)計算 lngD = lngAllS / (24 * 60 * 60); // 日 lngS = lngAllS % (24 * 60 * 60); // 残りの秒数 lngH = lngS / (60 * 60); // 時 lngS = lngS % (60 * 60); // 残りの秒数 lngM = lngS / 60; // 分 lngS = lngS % 60; // 秒
// 現在の日時(DateTime)計算 DateTime dtTime = new DateTime(1900, 1, 1); dtTime = dtTime.AddDays(lngD); dtTime = dtTime.AddHours(lngH); dtTime = dtTime.AddMinutes(lngM); dtTime = dtTime.AddSeconds(lngS);
// グリニッジ標準時から日本時間への変更 dtTime = dtTime.AddHours(9);
// 現在の日時表示 System.Diagnostics.Trace.WriteLine(dtTime);
// システム時計の日時設定 Boolean ret = SetSysTime(dtTime); if (ret == false) { //エラー処理 }
//Processオブジェクトを作成 System.Diagnostics.Process p = new System.Diagnostics.Process();
//ComSpec(cmd.exe)のパスを取得して、FileNameプロパティに指定 p.StartInfo.FileName = System.Environment.GetEnvironmentVariable("ComSpec"); //出力を読み取れるようにする p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = false; //ウィンドウを表示しないようにする p.StartInfo.CreateNoWindow = true; //コマンドラインを指定("/c"は実行後閉じるために必要)
p.StartInfo.Arguments = @"/c w32tm /stripchart /computer:" + 192.168.0.10 + " /samples:1";
//起動 p.Start();
//出力を読み取る string results = p.StandardOutput.ReadToEnd();
//プロセス終了まで待機する //WaitForExitはReadToEndの後である必要がある //(親プロセス、子プロセスでブロック防止のため) p.WaitForExit(); p.Close(); int index1 = results.IndexOf("o:+"); int index2 = results.IndexOf("s ["); //出力された結果を表示 string strms = Mid(results, index1+3, index2-2 - index1); Double dms = 0;
double.TryParse(strms, out dms); // 現在の日時(DateTime)計算 DateTime dtReTime = DateTime.Now.AddMilliseconds(dms * 1000); // システム時計の再校正 Boolean ret2 = SetSysTime(dtReTime); if (ret2 == true) { //エラー処理 } }
|